Salome HOME
Synchronize adm files
[modules/geom.git] / src / Material / Material_Model.cxx
1 // Copyright (C) 2007-2014  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, or (at your option) any later version.
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 #include <QMutexLocker>
29
30 /*!
31   \brief Constructor
32
33   Create new SALOME material model with default properties.
34 */
35 Material_Model::Material_Model()
36 {
37   myReflection  = ReflectionList(4);
38   init(); // set default properties
39 }
40
41 /*!
42   \brief Destructor
43 */
44 Material_Model::~Material_Model()
45 {
46 }
47
48 /*!
49   \brief Initialize material data from the given properties list
50   \param props material properties
51   \sa toProperties()
52 */
53 void Material_Model::fromProperties( const QString& props )
54 {
55   // reset to default values
56   init();
57
58   // parse material properties
59   QStringList propList = props.split( ":", QString::SkipEmptyParts );
60   foreach ( QString prop, propList ) 
61   {
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();
66     bool dblOk, boolOk;
67     double dblValue  = data.toDouble( &dblOk );
68     bool   boolValue = (bool)( data.toInt( &boolOk ) );
69     QColor colorValue;
70     
71     if      ( key == "ambientcolor" && Qtx::stringToColor( data, colorValue ) ) {
72       setColor( Ambient, colorValue );
73     }
74     else if ( key == "diffusecolor" && Qtx::stringToColor( data, colorValue ) ) {
75       setColor( Diffuse, colorValue );
76     }
77     else if ( key == "specularcolor" && Qtx::stringToColor( data, colorValue ) ) {
78       setColor( Specular, colorValue );
79     }
80     else if ( key == "emissivecolor" && Qtx::stringToColor( data, colorValue ) ) {
81       setColor( Emissive, colorValue );
82     }
83     else if ( key == "frontambientcoefficient" && dblOk ) {
84       setReflection( Ambient, dblValue );
85     }
86     else if ( key == "backambientcoefficient" && dblOk ) {
87       setReflection( Ambient, dblValue, false );
88     }
89     else if ( key == "frontdiffusecoefficient" && dblOk ) {
90       setReflection( Diffuse, dblValue );
91     }
92     else if ( key == "backdiffusecoefficient" && dblOk ) {
93       setReflection( Diffuse, dblValue, false );
94     }
95     else if ( key == "frontspecularcoefficient" && dblOk ) {
96       setReflection( Specular, dblValue );
97     }
98     else if ( key == "backspecularcoefficient" && dblOk ) {
99       setReflection( Specular, dblValue, false );
100     }
101     else if ( key == "frontemissivecoefficient" && dblOk ) {
102       setReflection( Emissive, dblValue );
103     }
104     else if ( key == "backemissivecoefficient" && dblOk ) {
105       setReflection( Emissive, dblValue, false );
106     }
107     else if ( key == "frontshininess" && dblOk ) {
108       setShininess( dblValue );
109     }
110     else if ( key == "backshininess" && dblOk ) {
111       setShininess( dblValue, false );
112     }
113     else if ( key == "transparency" && dblOk ) {
114       setTransparency( dblValue );
115     }
116     else if ( key == "physical" && boolOk ) {
117       setPhysical( boolValue );
118     }
119     else if ( key == "ambient" && boolOk ) {
120       setReflection( Ambient, boolValue );
121     }
122     else if ( key == "diffuse" && boolOk ) {
123       setReflection( Diffuse, boolValue );
124     }
125     else if ( key == "specular" && boolOk ) {
126       setReflection( Specular, boolValue );
127     }
128     else if ( key == "emissive" && boolOk ) {
129       setReflection( Emissive, boolValue );
130     }
131   }
132 }
133
134 /*!
135   \brief Get material properties string representation
136   \return string representing of material properties
137   \sa fromProperties()
138 */
139 QString Material_Model::toProperties()
140 {
141   QStringList props;
142   QString fmt = "%1=%2";
143
144   // physical
145   props << fmt.arg( "Physical" ).arg( isPhysical() );
146
147   // shininess
148   props << fmt.arg( "FrontShininess" ).arg( QString::number ( shininess( true ), 'g', 4 ) ) << fmt.arg( "BackShininess" ).arg( QString::number ( shininess( false ), 'g', 4 ) );
149
150   //transparency
151   props << fmt.arg( "Transparency" ).arg( transparency() );
152
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 ) );
158
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 ) );
164
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 ) );
170
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 ) );
176
177   return props.join( ":" );
178 }
179
180 /*!
181   \brief Initialize material model from the resources
182
183   This function can be used to retrieve material properties from the resource file.
184
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)
187   \sa toResources()
188 */
189 void Material_Model::fromResources( const QString& material, Material_ResourceMgr* resMgr )
190 {
191   static QString common = "[common]";
192   
193   // reset to default values
194   init();
195
196   // material name is not specified: use default values
197   if ( material.isEmpty() ) return;
198
199   if ( !resMgr )
200     resMgr = Material_ResourceMgr::resourceMgr();
201
202   // lock resources manager
203   QMutexLocker lock( &resMgr->myMutex );
204
205   // read common section
206   if ( material != common && resMgr->hasSection( common ) )
207     read( common, resMgr );
208
209   // read material section
210   read( material, resMgr );
211 }
212
213 void Material_Model::read( const QString& material, Material_ResourceMgr* resMgr )
214 {
215   // physical
216   if ( resMgr->hasValue( material, "physical" ) ) {
217     setPhysical( resMgr->booleanValue( material, "physical" ) );
218   }
219
220   // shininess
221   if ( resMgr->hasValue( material, "front_shininess" ) ) {
222     setShininess( resMgr->doubleValue( material, "front_shininess" ) );
223   }
224   if ( resMgr->hasValue( material, "back_shininess" ) ) {
225     setShininess( resMgr->doubleValue( material, "back_shininess" ), false );
226   }
227
228   // transparency
229   if ( resMgr->hasValue( material, "transparency" ) ) {
230     setTransparency( resMgr->doubleValue( material, "transparency" ) );
231   }
232
233   // ambient reflection
234   if ( resMgr->hasValue( material, "ambient-color" ) ) {
235     setColor( Ambient, resMgr->colorValue( material, "ambient-color" ) );
236   }
237   if ( resMgr->hasValue( material, "front_ambient-coefficient" ) ) {
238     setReflection( Ambient, resMgr->doubleValue( material, "front_ambient-coefficient" ) );
239   }
240   if ( resMgr->hasValue( material, "back_ambient-coefficient" ) ) {
241     setReflection( Ambient, resMgr->doubleValue( material, "back_ambient-coefficient" ), false );
242   }
243   if ( resMgr->hasValue( material, "ambient" ) ) {
244     setReflection( Ambient, resMgr->booleanValue( material, "ambient" ) );
245   }
246
247   // diffuse reflection
248   if ( resMgr->hasValue( material, "diffuse-color" ) ) {
249     setColor( Diffuse, resMgr->colorValue( material, "diffuse-color" ) );
250   }
251   if ( resMgr->hasValue( material, "front_diffuse-coefficient" ) ) {
252     setReflection( Diffuse, resMgr->doubleValue( material, "front_diffuse-coefficient" ) );
253   }
254   if ( resMgr->hasValue( material, "back_diffuse-coefficient" ) ) {
255     setReflection( Diffuse, resMgr->doubleValue( material, "back_diffuse-coefficient" ), false );
256   }
257   if ( resMgr->hasValue( material, "diffuse" ) ) {
258     setReflection( Diffuse, resMgr->booleanValue( material, "diffuse" ) );
259   }
260
261   // specular reflection
262   if ( resMgr->hasValue( material, "specular-color" ) ) {
263     setColor( Specular, resMgr->colorValue( material, "specular-color" ) );
264   }
265   if ( resMgr->hasValue( material, "front_specular-coefficient" ) ) {
266     setReflection( Specular, resMgr->doubleValue( material, "front_specular-coefficient" ) );
267   }
268   if ( resMgr->hasValue( material, "back_specular-coefficient" ) ) {
269     setReflection( Specular, resMgr->doubleValue( material, "back_specular-coefficient" ), false );
270   }
271   if ( resMgr->hasValue( material, "specular" ) ) {
272     setReflection( Specular, resMgr->booleanValue( material, "specular" ) );
273   }
274
275   // emissive reflection
276   if ( resMgr->hasValue( material, "emissive-color" ) ) {
277     setColor( Emissive, resMgr->colorValue( material, "emissive-color" ) );
278   }
279   if ( resMgr->hasValue( material, "front_emissive-coefficient" ) ) {
280     setReflection( Emissive, resMgr->doubleValue( material, "front_emissive-coefficient" ) );
281   }
282   if ( resMgr->hasValue( material, "back_emissive-coefficient" ) ) {
283     setReflection( Emissive, resMgr->doubleValue( material, "back_emissive-coefficient" ), false );
284   }
285   if ( resMgr->hasValue( material, "emissive" ) ) {
286     setReflection( Emissive, resMgr->booleanValue( material, "emissive" ) );
287   }
288 }
289
290 /*!
291   \brief Save material properties to the resource file.
292   \param material material name
293   \param resMgr resource manager
294   \sa fromResources()
295 */
296 void Material_Model::toResources( const QString& material, Material_ResourceMgr* resMgr )
297 {
298   if ( resMgr && !material.isEmpty() ) {
299     // lock resources manager
300     QMutexLocker lock( &resMgr->myMutex );
301   
302     // remove resources section (to clean-up all previous properties)
303     resMgr->remove( material );
304
305     // physical
306     resMgr->setValue( material, "physical", isPhysical() );
307
308     // shininess
309     resMgr->setValue( material, "front_shininess", shininess( true) );
310     resMgr->setValue( material, "back_shininess", shininess( false ) );
311
312     // transparency
313     resMgr->setValue( material, "transparency", transparency() );
314
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 ) );
321
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 ) );
328
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 ) );
335
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 ) );
342   }
343 }
344
345 /*!
346   \brief Get material type
347   \return \c true if material is physical or \c false otherwise
348   \sa setPhysical()
349 */
350 bool Material_Model::isPhysical() const
351 {
352   return myIsPhysical;
353 }
354
355 /*!
356   \brief Set material type
357   \param value \c true if material is physical or \c false otherwise
358   \sa isPhysical()
359 */
360 void Material_Model::setPhysical( bool value )
361 {
362   myIsPhysical = value;
363 }
364
365 /*!
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)
370 */
371 bool Material_Model::hasReflection( ReflectionType type ) const
372 {
373   bool value = false;
374   if ( type >= 0 && type < 4 )
375     value = myReflection[ type ].enabled;
376   return value;
377 }
378
379 /*!
380   \brief Enable/disable given reflection type
381   \param type reflection type
382   \param value boolean flag
383   \sa hasReflection()
384 */
385 void Material_Model::setReflection( ReflectionType type, bool value )
386 {
387   if ( type >= 0 && type < 4 )
388     myReflection[ type ].enabled = value;
389 }
390
391 /*!
392   \brief Get color value for the given reflection type
393   \param type reflection type
394   \return color associated with the specified reflection type
395   \sa setColor()
396 */
397 QColor Material_Model::color( ReflectionType type ) const
398 {
399   QColor value;
400   if ( type >= 0 && type < 4 )
401     value = myReflection[ type ].color;
402   return value;
403 }
404
405 /*!
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
409   \sa color()
410 */
411 void Material_Model::setColor( ReflectionType type, const QColor& value )
412 {
413   if ( type >= 0 && type < 4 )
414     myReflection[ type ].color = value;
415 }
416
417 /*!
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)
423 */
424 double Material_Model::reflection( ReflectionType type, bool theIsFront ) const
425 {
426   double value = 0.0;
427   if ( type >= 0 && type < 4 )
428   {
429     if ( theIsFront )
430       value = myReflection[ type ].front_coef;
431     else
432       value = myReflection[ type ].back_coef;
433   }
434   return value;
435 }
436
437 /*!
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)
443 */
444 void Material_Model::setReflection( ReflectionType type, double value, bool theIsFront )
445 {
446   if ( type >= 0 && type < 4 )
447   {
448     if ( theIsFront )
449       myReflection[ type ].front_coef = value;
450     else
451       myReflection[ type ].back_coef = value;
452   }
453 }
454
455 /*!
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 )
460 */
461 double Material_Model::shininess( bool theIsFront ) const
462 {
463   if ( theIsFront )
464     return myFrontShininess;
465   else
466     return myBackShininess;
467 }
468
469 /*!
470   \brief Set shininess value
471   \param value new shininess value
472   \param theIsFront boolean flag for choosing side
473   \sa shininess( bool = true )
474 */
475 void Material_Model::setShininess( double value, bool theIsFront )
476 {
477   if ( theIsFront )
478     myFrontShininess = value;
479   else
480     myBackShininess = value;
481 }
482
483 /*!
484   \brief Get transparency value
485   \return transparency value of the material
486   \sa setTransparency()
487 */
488 double Material_Model::transparency() const
489 {
490   return myTransparency;
491 }
492
493 /*!
494   \brief Set transparency value
495   \param value new transparency value
496   \sa transparency()
497 */
498 void Material_Model::setTransparency( double value )
499 {
500   myTransparency = value;
501 }
502
503 /*!
504   \brief Initialize material model with default values
505 */
506 void Material_Model::init()
507 {  
508   QColor c;
509
510   // non-physical by default
511   setPhysical( false );
512   // shininess
513   setShininess( 0.039 );
514   setShininess( 0.039, false );
515   // transparency
516   setTransparency( 0.0 );
517
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 );
524
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 );
531
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 );
538
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 );
545 }
546
547 /*!
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
551 */
552 Graphic3d_MaterialAspect Material_Model::getMaterialOCCAspect( bool theIsFront )
553 {
554   // Get material aspect from the current model
555   Graphic3d_MaterialAspect aspect;
556
557   QColor c;
558   
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 ) );
563   }
564   aspect.SetAmbient( reflection( Ambient, theIsFront ));
565   if ( hasReflection( Ambient ) )
566     aspect.SetReflectionModeOn( Graphic3d_TOR_AMBIENT );
567   else
568     aspect.SetReflectionModeOff( Graphic3d_TOR_AMBIENT );
569   
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 ) );
574   }
575   aspect.SetDiffuse( reflection( Diffuse, theIsFront ));
576   if ( hasReflection( Diffuse ) )
577     aspect.SetReflectionModeOn( Graphic3d_TOR_DIFFUSE );
578   else
579     aspect.SetReflectionModeOff( Graphic3d_TOR_DIFFUSE );
580
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 ) );
585   }
586   aspect.SetSpecular( reflection( Specular, theIsFront ));
587   if ( hasReflection( Specular ) )
588     aspect.SetReflectionModeOn( Graphic3d_TOR_SPECULAR );
589   else
590     aspect.SetReflectionModeOff( Graphic3d_TOR_SPECULAR );
591
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 ) );
596   }
597   aspect.SetEmissive( reflection( Emissive, theIsFront ));
598   if ( hasReflection( Emissive ) )
599     aspect.SetReflectionModeOn( Graphic3d_TOR_EMISSION );
600   else
601     aspect.SetReflectionModeOff( Graphic3d_TOR_EMISSION );
602   
603   // shininess
604   aspect.SetShininess( shininess( theIsFront ) );
605
606   // transparency
607   aspect.SetTransparency( transparency() );
608
609   // material type
610   aspect.SetMaterialType( isPhysical() ? Graphic3d_MATERIAL_PHYSIC : Graphic3d_MATERIAL_ASPECT );
611
612   return aspect;
613 }
614
615 /*!
616   \brief Construct VTK property from material model
617   \param theIsFront boolean flag for choosing side
618   \return VTK property with correspondent material properties
619 */
620 GEOM_VTKPropertyMaterial* Material_Model::getMaterialVTKProperty( bool theIsFront )
621 {
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
626
627   // Get material properties from the current model
628   GEOM_VTKPropertyMaterial* prop = GEOM_VTKPropertyMaterial::New();
629
630   QColor c;
631
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 ) );
637   }
638
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 ) );
644   }
645
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 ) );
651   }
652
653   // shininess
654   prop->SetSpecularPower( shininess( theIsFront )*100.0 );
655
656   // transparency
657   prop->SetOpacity( 1 - transparency() );
658
659   // material type
660   prop->SetPhysical( isPhysical() );
661
662   return prop;
663 }
664