1 /* This file is part of Shapes.
3 * Shapes is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
8 * Shapes 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
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with Shapes. If not, see <http://www.gnu.org/licenses/>.
16 * Copyright 2008 Henrik Tidefelt
21 #include "lighttypes.h"
24 #include "constructorrepresentation.h"
26 using namespace Shapes
;
29 Lang::SpecularReflection::SpecularReflection( )
32 Lang::SpecularReflection::~SpecularReflection( )
35 DISPATCHIMPL( SpecularReflection
);
37 RefCountPtr
< const Lang::Class
> Lang::SpecularReflection::TypeID( new Lang::SystemFinalClass( strrefdup( "SpecularReflection" ) ) );
38 TYPEINFOIMPL( SpecularReflection
);
41 Lang::SpecularReflection::gcMark( Kernel::GCMarkedSet
& marked
)
44 Lang::SpecularReflectionTerm::SpecularReflectionTerm( double weight
, double exponent
)
45 : weight_( weight
), exponent_( exponent
)
48 Lang::SpecularReflectionTerm::~SpecularReflectionTerm( )
52 Lang::SpecularReflectionTerm::weight( ) const
57 RefCountPtr
< const Lang::SpecularReflection
>
58 Lang::SpecularReflectionTerm::multiply( double scalar
) const
60 return RefCountPtr
< const Lang::SpecularReflection
>( new Lang::SpecularReflectionTerm( scalar
* weight_
, exponent_
) );
65 Lang::SpecularReflectionTerm::illuminate( const Concrete::Coords3D
& point
, const Concrete::Length eyez
, const Concrete::UnitFloatTriple
& unitNormal
, const Lang::GrayLight
& light
) const
67 return light
.illuminateGray( point
, eyez
, unitNormal
, *this );
71 Lang::SpecularReflectionTerm::illuminate( const Concrete::Coords3D
& point
, const Concrete::Length eyez
, const Concrete::UnitFloatTriple
& unitNormal
, const Lang::RGBLight
& light
) const
73 return light
.illuminateRGB( point
, eyez
, unitNormal
, *this );
77 Lang::SpecularReflectionTerm::illuminate( const Concrete::Coords3D
& point
, const Concrete::Length eyez
, const Concrete::UnitFloatTriple
& unitNormal
, const Concrete::Gray
& autoIntensity
) const
79 // According to my calculations, the autoIntensity seen by the eye does not change with the distance to the object;
80 // one the size of the object changes, which will make the received power decrease with distance.
81 return Concrete::Gray( weight_
* pow( fabs( Concrete::inner( unitNormal
, ( Concrete::Coords3D( 0, 0, eyez
) - point
).direction( ) ) ), exponent_
) * autoIntensity
.gr_
);
85 Lang::SpecularReflectionTerm::illuminate( const Concrete::Coords3D
& point
, const Concrete::Length eyez
, const Concrete::UnitFloatTriple
& unitNormal
, const Concrete::RGB
& autoIntensity
) const
87 // According to my calculations, the autoIntensity seen by the eye does not change with the distance to the object;
88 // one the size of the object changes, which will make the received power decrease with distance.
89 double a
= weight_
* pow( fabs( Concrete::inner( unitNormal
, ( Concrete::Coords3D( 0, 0, eyez
) - point
).direction( ) ) ), exponent_
);
90 return Concrete::RGB( a
* autoIntensity
.r_
, a
* autoIntensity
.g_
, a
* autoIntensity
.b_
);
94 Lang::SpecularReflectionTerm::exponent( ) const
100 Lang::SpecularReflectionNull::SpecularReflectionNull( )
103 Lang::SpecularReflectionNull::~SpecularReflectionNull( )
107 Lang::SpecularReflectionNull::weight( ) const
112 RefCountPtr
< const Lang::SpecularReflection
>
113 Lang::SpecularReflectionNull::multiply( double scalar
) const
115 return Lang::THE_SPECULARREFLECTION_NULL
;
119 Lang::SpecularReflectionNull::illuminate( const Concrete::Coords3D
& point
, const Concrete::Length eyez
, const Concrete::UnitFloatTriple
& unitNormal
, const Lang::GrayLight
& light
) const
121 return Concrete::Gray( 0. );
125 Lang::SpecularReflectionNull::illuminate( const Concrete::Coords3D
& point
, const Concrete::Length eyez
, const Concrete::UnitFloatTriple
& unitNormal
, const Lang::RGBLight
& light
) const
127 return Concrete::RGB( 0., 0., 0. );
131 Lang::SpecularReflectionNull::illuminate( const Concrete::Coords3D
& point
, const Concrete::Length eyez
, const Concrete::UnitFloatTriple
& unitNormal
, const Concrete::Gray
& autoIntensity
) const
133 return Concrete::Gray( 0. );
137 Lang::SpecularReflectionNull::illuminate( const Concrete::Coords3D
& point
, const Concrete::Length eyez
, const Concrete::UnitFloatTriple
& unitNormal
, const Concrete::RGB
& autoIntensity
) const
139 return Concrete::RGB( 0., 0., 0. );
143 Lang::SpecularReflectionPair::SpecularReflectionPair( const RefCountPtr
< const Lang::SpecularReflection
> & car
, const RefCountPtr
< const Lang::SpecularReflection
> & cdr
)
144 : car_( car
), cdr_( cdr
)
147 Lang::SpecularReflectionPair::~SpecularReflectionPair( )
151 Lang::SpecularReflectionPair::weight( ) const
153 return car_
->weight( ) + cdr_
->weight( );
156 RefCountPtr
< const Lang::SpecularReflection
>
157 Lang::SpecularReflectionPair::multiply( double scalar
) const
159 return RefCountPtr
< const Lang::SpecularReflection
>
160 ( new Lang::SpecularReflectionPair( car_
->multiply( scalar
), cdr_
->multiply( scalar
) ) );
165 Lang::SpecularReflectionPair::illuminate( const Concrete::Coords3D
& point
, const Concrete::Length eyez
, const Concrete::UnitFloatTriple
& unitNormal
, const Lang::GrayLight
& light
) const
167 return car_
->illuminate( point
, eyez
, unitNormal
, light
).addNoCheck( cdr_
->illuminate( point
, eyez
, unitNormal
, light
) );
171 Lang::SpecularReflectionPair::illuminate( const Concrete::Coords3D
& point
, const Concrete::Length eyez
, const Concrete::UnitFloatTriple
& unitNormal
, const Lang::RGBLight
& light
) const
173 return car_
->illuminate( point
, eyez
, unitNormal
, light
).addNoCheck( cdr_
->illuminate( point
, eyez
, unitNormal
, light
) );
177 Lang::SpecularReflectionPair::illuminate( const Concrete::Coords3D
& point
, const Concrete::Length eyez
, const Concrete::UnitFloatTriple
& unitNormal
, const Concrete::Gray
& autoIntensity
) const
179 return car_
->illuminate( point
, eyez
, unitNormal
, autoIntensity
).addNoCheck( cdr_
->illuminate( point
, eyez
, unitNormal
, autoIntensity
) );
183 Lang::SpecularReflectionPair::illuminate( const Concrete::Coords3D
& point
, const Concrete::Length eyez
, const Concrete::UnitFloatTriple
& unitNormal
, const Concrete::RGB
& autoIntensity
) const
185 return car_
->illuminate( point
, eyez
, unitNormal
, autoIntensity
).addNoCheck( cdr_
->illuminate( point
, eyez
, unitNormal
, autoIntensity
) );
189 Lang::LightSource::LightSource( bool shadows
)
190 : shadows_( shadows
)
193 DISPATCHIMPL( LightSource
);
195 RefCountPtr
< const Lang::Class
> Lang::LightSource::TypeID( new Lang::SystemFinalClass( strrefdup( "LightSource" ) ) );
196 TYPEINFOIMPL( LightSource
);
198 Lang::LightSource::~LightSource( )
201 RefCountPtr
< const Lang::Geometric3D
>
202 Lang::LightSource::transformed( const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Geometric3D
> & self
) const
204 return typed_transformed( tf
);
207 RefCountPtr
< const Lang::Geometric2D
>
208 Lang::LightSource::to2D( const Kernel::PassedDyn
& dyn
, const RefCountPtr
< const Lang::Geometric3D
> & self
) const
210 throw Exceptions::MiscellaneousRequirement( "A LightSource cannot be viewed in 2D." );
214 Lang::LightSource::gcMark( Kernel::GCMarkedSet
& marked
)
218 Lang::GrayLight::GrayLight( bool shadows
)
219 : Lang::LightSource( shadows
)
222 Lang::GrayLight::~GrayLight( )
226 Lang::RGBLight::RGBLight( bool shadows
)
227 : Lang::LightSource( shadows
)
230 Lang::RGBLight::~RGBLight( )
234 Lang::AmbientLightGray::AmbientLightGray( const Concrete::Gray
& intensity
)
235 : Lang::GrayLight( false ), intensity_( intensity
)
238 Lang::AmbientLightGray::~AmbientLightGray( )
241 RefCountPtr
< const Lang::LightSource
>
242 Lang::AmbientLightGray::typed_transformed( const Lang::Transform3D
& tf
) const
244 // It's sad that we don't have access to the self reference, so that it could be returned instead of a new object with is just a copy of ourselves.
245 return RefCountPtr
< const Lang::LightSource
>( new Lang::AmbientLightGray( intensity_
) );
249 Lang::AmbientLightGray::illuminateRGB( const Concrete::Coords3D
& point
, const Concrete::Length eyez
, const Concrete::UnitFloatTriple
& unitNormal
, const Lang::SpecularReflectionTerm
& refl
) const
251 double a
= intensity_
.gr_
* refl
.weight( );
252 return Concrete::RGB( a
, a
, a
);
256 Lang::AmbientLightGray::illuminateGray( const Concrete::Coords3D
& point
, const Concrete::Length eyez
, const Concrete::UnitFloatTriple
& unitNormal
, const Lang::SpecularReflectionTerm
& refl
) const
258 return Concrete::Gray( intensity_
.gr_
* refl
.weight( ) );
261 Lang::AmbientLightRGB::AmbientLightRGB( const Concrete::RGB
& intensity
)
262 : Lang::RGBLight( false ), intensity_( intensity
)
265 Lang::AmbientLightRGB::~AmbientLightRGB( )
268 RefCountPtr
< const Lang::LightSource
>
269 Lang::AmbientLightRGB::typed_transformed( const Lang::Transform3D
& tf
) const
271 return RefCountPtr
< const Lang::LightSource
>( new Lang::AmbientLightRGB( intensity_
) );
275 Lang::AmbientLightRGB::illuminateRGB( const Concrete::Coords3D
& point
, const Concrete::Length eyez
, const Concrete::UnitFloatTriple
& unitNormal
, const Lang::SpecularReflectionTerm
& refl
) const
277 const double w
= refl
.weight( );
278 return Concrete::RGB( intensity_
.r_
* w
, intensity_
.g_
* w
, intensity_
.b_
* w
);
281 Lang::SpecularLightGray::SpecularLightGray( const Concrete::Coords3D
& p
, const Concrete::Gray
& intensity
, Concrete::Length intensityRadius
, bool shadows
)
282 : Lang::GrayLight( shadows
), p_( p
), intensity_( intensity
), intensityRadius_( intensityRadius
)
285 Lang::SpecularLightGray::~SpecularLightGray( )
288 RefCountPtr
< const Lang::LightSource
>
289 Lang::SpecularLightGray::typed_transformed( const Lang::Transform3D
& tf
) const
291 return RefCountPtr
< const Lang::LightSource
>( new Lang::SpecularLightGray( p_
.transformed( tf
), intensity_
, intensityRadius_
, shadows_
) );
295 Lang::SpecularLightGray::illuminateRGB( const Concrete::Coords3D
& point
, const Concrete::Length eyez
, const Concrete::UnitFloatTriple
& unitNormal
, const Lang::SpecularReflectionTerm
& refl
) const
297 // Refer to SpecularLightGray::illuminateGray for comments regarding this code.
298 // This function shall be analogous to that function.
300 Concrete::Coords3D rLight
= p_
- point
;
301 Concrete::Coords3D rEye
= Concrete::Coords3D( Concrete::ZERO_LENGTH
, Concrete::ZERO_LENGTH
, eyez
) - point
;
302 Concrete::Length dLight
= rLight
.norm( );
303 Concrete::Length dEye
= rEye
.norm( );
304 Concrete::UnitFloatTriple rHatLight
= rLight
.direction( dLight
);
305 Concrete::UnitFloatTriple rHatEye
= rEye
.direction( dEye
);
306 Concrete::Length dTot
= dLight
+ dEye
;
308 Concrete::UnitFloatTriple rHatReflection
= unitNormal
.reflect( rHatLight
);
310 // This breaks the Phong model, but I want reflection in all directions!
311 // ... as long as the light and the eye are on the same side of the surface!
312 if( ( Concrete::inner( unitNormal
, rHatEye
) > 0 ) != ( Concrete::inner( unitNormal
, rHatLight
) > 0 ) )
314 return Concrete::RGB( 0, 0, 0 );
316 const double cPhong2
= cos( 0.5 * acos( Concrete::inner( rHatReflection
, rHatEye
) ) );
318 // Just in case numeric errors make c negative anyway...
321 return Concrete::RGB( 0, 0, 0 );
324 // Further, I want something that becomes ambient when refl.exponent == 0.
327 if( refl
.exponent( ) < 1 )
329 cAmb
= pow( fabs( Concrete::inner( unitNormal
, rHatLight
) ), 1 - refl
.exponent( ) );
333 if( intensityRadius_
< Concrete::HUGE_LENGTH
)
335 rRel
= intensityRadius_
/ dTot
;
338 double a
= intensity_
.mulNoCheck( refl
.weight( ) * pow( cPhong2
, refl
.exponent( ) ) * cAmb
* rRel
* rRel
).gr_
;
339 return Concrete::RGB( a
, a
, a
);
343 Lang::SpecularLightGray::illuminateGray( const Concrete::Coords3D
& point
, const Concrete::Length eyez
, const Concrete::UnitFloatTriple
& unitNormal
, const Lang::SpecularReflectionTerm
& refl
) const
345 Concrete::Coords3D rLight
= p_
- point
;
346 Concrete::Coords3D rEye
= Concrete::Coords3D( Concrete::ZERO_LENGTH
, Concrete::ZERO_LENGTH
, eyez
) - point
;
347 Concrete::Length dLight
= rLight
.norm( );
348 Concrete::Length dEye
= rEye
.norm( );
349 Concrete::UnitFloatTriple rHatLight
= rLight
.direction( dLight
);
350 Concrete::UnitFloatTriple rHatEye
= rEye
.direction( dEye
);
351 Concrete::Length dTot
= dLight
+ dEye
;
353 Concrete::UnitFloatTriple rHatReflection
= unitNormal
.reflect( rHatLight
);
355 // std::cerr << "Point: " << Helpers::shapesFormat( point ) << std::endl ;
356 // std::cerr << "rLight: " << Helpers::shapesFormat( rLight ) << std::endl ;
357 // std::cerr << "Surface normal: " << Helpers::shapesFormat( unitNormal ) << std::endl ;
358 // std::cerr << "rHatReflection: " << Helpers::shapesFormat( rHatReflection ) << std::endl ;
359 // std::cerr << "rEye: " << Helpers::shapesFormat( rEye ) << std::endl ;
360 // std::cerr << "rHatEye: " << Helpers::shapesFormat( rHatEye ) << std::endl ;
361 // std::cerr << "Phong's angle: " << acos( Concrete::inner( rHatReflection, rHatEye ) ) << std::endl ;
363 // This breaks the Phong model, but I want reflection in all directions!
364 // ... as long as the light and the eye are on the same side of the surface!
365 if( ( Concrete::inner( unitNormal
, rHatEye
) > 0 ) != ( Concrete::inner( unitNormal
, rHatLight
) > 0 ) )
367 return Concrete::Gray( 0 );
369 const double cPhong2
= cos( 0.5 * acos( Concrete::inner( rHatReflection
, rHatEye
) ) );
371 // Just in case numeric errors make c negative anyway...
374 return Concrete::Gray( 0 );
377 // Further, I want something that becomes ambient when refl.exponent == 0.
380 if( refl
.exponent( ) < 1 )
382 cAmb
= pow( fabs( Concrete::inner( unitNormal
, rHatLight
) ), 1 - refl
.exponent( ) );
386 if( intensityRadius_
< Concrete::HUGE_LENGTH
)
388 rRel
= intensityRadius_
/ dTot
;
391 // std::cerr << " Intensity: " << intensity_.gr_ << std::endl ;
392 // std::cerr << " Phong2: " << pow( cPhong2, refl.exponent( ) ) << std::endl ;
393 // std::cerr << " Amb2: " << pow( cIn, 1 / ( 1 + 10 * refl.exponent( ) ) ) << std::endl ;
394 // std::cerr << " Distance factor: " << rRel * rRel << std::endl ;
395 // std::cerr << " Total: " << refl.weight( ) * pow( c, refl.exponent( ) ) * rRel * rRel * intensity_.gr_ << std::endl ;
397 return intensity_
.mulNoCheck( refl
.weight( ) * pow( cPhong2
, refl
.exponent( ) ) * cAmb
* rRel
* rRel
);
400 Lang::SpecularLightRGB::SpecularLightRGB( const Concrete::Coords3D
& p
, const Concrete::RGB
& intensity
, Concrete::Length intensityRadius
, bool shadows
)
401 : Lang::RGBLight( shadows
), p_( p
), intensity_( intensity
), intensityRadius_( intensityRadius
)
404 Lang::SpecularLightRGB::~SpecularLightRGB( )
407 RefCountPtr
< const Lang::LightSource
>
408 Lang::SpecularLightRGB::typed_transformed( const Lang::Transform3D
& tf
) const
410 return RefCountPtr
< const Lang::LightSource
>( new Lang::SpecularLightRGB( p_
.transformed( tf
), intensity_
, intensityRadius_
, shadows_
) );
414 Lang::SpecularLightRGB::illuminateRGB( const Concrete::Coords3D
& point
, const Concrete::Length eyez
, const Concrete::UnitFloatTriple
& unitNormal
, const Lang::SpecularReflectionTerm
& refl
) const
416 // Refer to SpecularLightGray::illuminateGray for comments regarding this code.
417 // This function shall be analogous to that function.
419 Concrete::Coords3D rLight
= p_
- point
;
420 Concrete::Coords3D rEye
= Concrete::Coords3D( Concrete::ZERO_LENGTH
, Concrete::ZERO_LENGTH
, eyez
) - point
;
421 Concrete::Length dLight
= rLight
.norm( );
422 Concrete::Length dEye
= rEye
.norm( );
423 Concrete::UnitFloatTriple rHatLight
= rLight
.direction( dLight
);
424 Concrete::UnitFloatTriple rHatEye
= rEye
.direction( dEye
);
425 Concrete::Length dTot
= dLight
+ dEye
;
427 Concrete::UnitFloatTriple rHatReflection
= unitNormal
.reflect( rHatLight
);
429 // This breaks the Phong model, but I want reflection in all directions!
430 const double cPhong2
= cos( 0.5 * acos( Concrete::inner( rHatReflection
, rHatEye
) ) );
432 // Just in case numeric errors make c negative anyway...
435 return Concrete::RGB( 0, 0, 0 );
438 // Further, I want something that becomes ambient when refl.exponent == 0.
441 if( refl
.exponent( ) < 1 )
443 cAmb
= pow( fabs( Concrete::inner( unitNormal
, rHatLight
) ), 1 - refl
.exponent( ) );
447 if( intensityRadius_
< Concrete::HUGE_LENGTH
)
449 rRel
= intensityRadius_
/ dTot
;
452 return intensity_
.mulNoCheck( refl
.weight( ) * pow( cPhong2
, refl
.exponent( ) ) * cAmb
* rRel
* rRel
);
455 Lang::DistantLightGray::DistantLightGray( const Concrete::UnitFloatTriple
& rHatLight
, const Concrete::Gray
& intensity
, bool shadows
)
456 : Lang::GrayLight( shadows
), rHatLight_( rHatLight
), intensity_( intensity
)
459 Lang::DistantLightGray::~DistantLightGray( )
462 RefCountPtr
< const Lang::LightSource
>
463 Lang::DistantLightGray::typed_transformed( const Lang::Transform3D
& tf
) const
465 return RefCountPtr
< const Lang::LightSource
>( new Lang::DistantLightGray( tf
.transformPlaneUnitNormal( rHatLight_
), intensity_
, shadows_
) );
469 Lang::DistantLightGray::illuminateRGB( const Concrete::Coords3D
& point
, const Concrete::Length eyez
, const Concrete::UnitFloatTriple
& unitNormal
, const Lang::SpecularReflectionTerm
& refl
) const
471 // Compare SpecularLightGray::illuminateGray.
473 Concrete::Coords3D rEye
= Concrete::Coords3D( Concrete::ZERO_LENGTH
, Concrete::ZERO_LENGTH
, eyez
) - point
;
474 Concrete::Length dEye
= rEye
.norm( );
475 Concrete::UnitFloatTriple rHatEye
= rEye
.direction( dEye
);
477 Concrete::UnitFloatTriple rHatReflection
= unitNormal
.reflect( rHatLight_
);
479 // This breaks the Phong model, but I want reflection in all directions!
480 const double cPhong2
= cos( 0.5 * acos( Concrete::inner( rHatReflection
, rHatEye
) ) );
482 // Just in case numeric errors make c negative anyway...
485 return Concrete::RGB( 0, 0, 0 );
488 // Further, I want something that becomes ambient when refl.exponent == 0.
491 if( refl
.exponent( ) < 1 )
493 cAmb
= pow( fabs( Concrete::inner( unitNormal
, rHatLight_
) ), 1 - refl
.exponent( ) );
496 double a
= intensity_
.mulNoCheck( refl
.weight( ) * pow( cPhong2
, refl
.exponent( ) ) * cAmb
).gr_
;
497 return Concrete::RGB( a
, a
, a
);
501 Lang::DistantLightGray::illuminateGray( const Concrete::Coords3D
& point
, const Concrete::Length eyez
, const Concrete::UnitFloatTriple
& unitNormal
, const Lang::SpecularReflectionTerm
& refl
) const
503 // Compare SpecularLightGray::illuminateGray.
505 Concrete::Coords3D rEye
= Concrete::Coords3D( Concrete::ZERO_LENGTH
, Concrete::ZERO_LENGTH
, eyez
) - point
;
506 Concrete::Length dEye
= rEye
.norm( );
507 Concrete::UnitFloatTriple rHatEye
= rEye
.direction( dEye
);
509 Concrete::UnitFloatTriple rHatReflection
= unitNormal
.reflect( rHatLight_
);
511 // This breaks the Phong model, but I want reflection in all directions!
512 const double cPhong2
= cos( 0.5 * acos( Concrete::inner( rHatReflection
, rHatEye
) ) );
514 // Just in case numeric errors make c negative anyway...
517 return Concrete::Gray( 0 );
520 // Further, I want something that becomes ambient when refl.exponent == 0.
523 if( refl
.exponent( ) < 1 )
525 cAmb
= pow( fabs( Concrete::inner( unitNormal
, rHatLight_
) ), 1 - refl
.exponent( ) );
528 return intensity_
.mulNoCheck( refl
.weight( ) * pow( cPhong2
, refl
.exponent( ) ) * cAmb
);
532 Lang::DistantLightRGB::DistantLightRGB( const Concrete::UnitFloatTriple
& rHatLight
, const Concrete::RGB
& intensity
, bool shadows
)
533 : Lang::RGBLight( shadows
), rHatLight_( rHatLight
), intensity_( intensity
)
536 Lang::DistantLightRGB::~DistantLightRGB( )
539 RefCountPtr
< const Lang::LightSource
>
540 Lang::DistantLightRGB::typed_transformed( const Lang::Transform3D
& tf
) const
542 return RefCountPtr
< const Lang::LightSource
>( new Lang::DistantLightRGB( tf
.transformPlaneUnitNormal( rHatLight_
), intensity_
, shadows_
) );
546 Lang::DistantLightRGB::illuminateRGB( const Concrete::Coords3D
& point
, const Concrete::Length eyez
, const Concrete::UnitFloatTriple
& rHatLight
, const Lang::SpecularReflectionTerm
& refl
) const
548 // Compare SpecularLightGray::illuminateGray.
550 Concrete::Coords3D rEye
= Concrete::Coords3D( Concrete::ZERO_LENGTH
, Concrete::ZERO_LENGTH
, eyez
) - point
;
551 Concrete::Length dEye
= rEye
.norm( );
552 Concrete::UnitFloatTriple rHatEye
= rEye
.direction( dEye
);
554 Concrete::UnitFloatTriple rHatReflection
= rHatLight_
.reflect( rHatLight_
);
556 // This breaks the Phong model, but I want reflection in all directions!
557 const double cPhong2
= cos( 0.5 * acos( Concrete::inner( rHatReflection
, rHatEye
) ) );
559 // Just in case numeric errors make c negative anyway...
562 return Concrete::RGB( 0, 0, 0 );
565 // Further, I want something that becomes ambient when refl.exponent == 0.
568 if( refl
.exponent( ) < 1 )
570 cAmb
= pow( fabs( Concrete::inner( rHatLight_
, rHatLight_
) ), 1 - refl
.exponent( ) );
573 return intensity_
.mulNoCheck( refl
.weight( ) * pow( cPhong2
, refl
.exponent( ) ) * cAmb
);
576 Lang::LightGroup::LightGroup( )
579 DISPATCHIMPL( LightGroup
);
581 RefCountPtr
< const Lang::Class
> Lang::LightGroup::TypeID( new Lang::SystemFinalClass( strrefdup( "LightGroup" ) ) );
582 TYPEINFOIMPL( LightGroup
);
584 Lang::LightGroup::~LightGroup( )
587 RefCountPtr
< const Lang::Geometric3D
>
588 Lang::LightGroup::transformed( const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Geometric3D
> & self
) const
590 return typed_transformed( tf
, self
.down_cast
< const Lang::LightGroup
>( ) );
593 RefCountPtr
< const Lang::Geometric2D
>
594 Lang::LightGroup::to2D( const Kernel::PassedDyn
& dyn
, const RefCountPtr
< const Lang::Geometric3D
> & self
) const
596 throw Exceptions::MiscellaneousRequirement( "Lights cannot exist in 2D." );
600 Lang::LightNull::LightNull( )
603 Lang::LightNull::~LightNull( )
606 RefCountPtr
< const Lang::LightGroup
>
607 Lang::LightNull::typed_transformed( const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::LightGroup
> & self
) const
613 Lang::LightNull::isNull( ) const
619 Lang::LightNull::containsRGB( ) const
625 Lang::LightNull::gcMark( Kernel::GCMarkedSet
& marked
)
629 Lang::LightPair::LightPair( const RefCountPtr
< const Lang::LightSource
> & car
, const RefCountPtr
< const Lang::LightGroup
> & cdr
)
630 : car_( car
), cdr_( cdr
)
633 Lang::LightPair::~LightPair( )
636 RefCountPtr
< const Lang::LightSource
>
637 Lang::LightPair::car( ) const
642 RefCountPtr
< const Lang::LightGroup
>
643 Lang::LightPair::cdr( ) const
648 RefCountPtr
< const Lang::LightGroup
>
649 Lang::LightPair::typed_transformed( const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::LightGroup
> & self
) const
651 return RefCountPtr
< const Lang::LightGroup
>( new Lang::LightPair( car_
->typed_transformed( tf
), cdr_
->typed_transformed( tf
, cdr_
) ) );
655 Lang::LightPair::isNull( ) const
661 Lang::LightPair::containsRGB( ) const
663 return ( ! car_
->isGray( ) ) || cdr_
->containsRGB( );
667 Lang::LightPair::gcMark( Kernel::GCMarkedSet
& marked
)
669 const_cast< Lang::LightSource
* >( car_
.getPtr( ) )->gcMark( marked
);
670 const_cast< Lang::LightGroup
* >( cdr_
.getPtr( ) )->gcMark( marked
);