1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
5  * Copyright (C) 2015-2021 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
23  */
24 
25 /**
26  * @file light.h
27  * @brief Declare and implement light sources.
28  */
29 
30 #ifndef LIGHT_H
31 #define LIGHT_H
32 
33 #include "ray.h"
34 #include "hitinfo.h"
35 
36 
37 /**
38  * A base light class to derive to implement other light classes.
39  */
40 class LIGHT
41 {
42 public:
LIGHT()43     LIGHT() { m_castShadow = true; }
44 
~LIGHT()45     virtual ~LIGHT() {}
46 
47     /**
48      * Get parameters from this light.
49      *
50      * @param aHitPoint: input hit position
51      * @param aOutVectorToLight a vector that points from the hit
52      *                          position in direction to the light
53      * @param aOutLightColor the color of this light
54      * @param aOutDistance the distance from the point to the light
55      */
56     virtual void GetLightParameters( const SFVEC3F& aHitPoint, SFVEC3F& aOutVectorToLight,
57                                      SFVEC3F& aOutLightColor, float& aOutDistance ) const = 0;
58 
SetCastShadows(bool aCastShadow)59     void SetCastShadows( bool aCastShadow ) { m_castShadow = aCastShadow; }
GetCastShadows()60     bool GetCastShadows() const { return m_castShadow; }
61 
62 protected:
63     bool m_castShadow;
64 };
65 
66 
67 /**
68  * Point light source based on http://ogldev.atspace.co.uk/www/tutorial20/tutorial20.html.
69  */
70 class POINT_LIGHT : public LIGHT
71 {
72 public:
POINT_LIGHT(const SFVEC3F & aPos,const SFVEC3F & aColor)73     POINT_LIGHT( const SFVEC3F& aPos, const SFVEC3F& aColor )
74     {
75         m_position     = aPos;
76         m_color        = aColor;
77         m_att_constant = 0.9f;
78         m_att_linear   = 0.0005f;
79         m_att_exp      = 0.001f;
80         m_castShadow   = true;
81     }
82 
83     // Imported functions from LIGHT
GetLightParameters(const SFVEC3F & aHitPoint,SFVEC3F & aOutVectorToLight,SFVEC3F & aOutLightColor,float & aOutDistance)84     void GetLightParameters( const SFVEC3F& aHitPoint, SFVEC3F& aOutVectorToLight,
85                              SFVEC3F& aOutLightColor, float& aOutDistance ) const override
86     {
87         const SFVEC3F vectorLight = m_position - aHitPoint;
88 
89         aOutDistance = glm::length( vectorLight );
90         aOutVectorToLight = vectorLight / aOutDistance; // normalize
91 
92         const float att = 1.0f / ( m_att_constant +
93                                    m_att_linear   * aOutDistance +
94                                    m_att_exp      * aOutDistance * aOutDistance );
95 
96         if( att <= 0.0f )
97             aOutLightColor = SFVEC3F( 0.0f, 0.0f, 0.0f );
98         else
99             aOutLightColor = m_color * att;
100     }
101 
102 private:
103     SFVEC3F m_position;
104     SFVEC3F m_color;
105 
106     float   m_att_constant;
107     float   m_att_linear;
108     float   m_att_exp;
109 };
110 
111 
112 /**
113  * A light source based only on a directional vector.
114  */
115 class DIRECTIONAL_LIGHT : public LIGHT
116 {
117 public:
DIRECTIONAL_LIGHT(const SFVEC3F & aDir,const SFVEC3F & aColor)118     DIRECTIONAL_LIGHT( const SFVEC3F& aDir, const SFVEC3F& aColor )
119     {
120         // Invert light direction and make sure it is normalized
121         m_inv_direction = glm::normalize( -aDir );
122         m_color         = aColor;
123         m_castShadow    = true; // Set as default to cast shadows
124     }
125 
126     /**
127      * Set directional light orientation.
128      *
129      * @param aDir is the vector defining the direction of the light source.
130      */
SetDirection(const SFVEC3F & aDir)131     void SetDirection( const SFVEC3F& aDir ) { m_inv_direction = -aDir; }
132 
133     // Imported functions from LIGHT
GetLightParameters(const SFVEC3F &,SFVEC3F & aOutVectorToLight,SFVEC3F & aOutLightColor,float & aOutDistance)134     void GetLightParameters( const SFVEC3F& /* aHitPoint */, SFVEC3F& aOutVectorToLight,
135                              SFVEC3F& aOutLightColor, float& aOutDistance ) const override
136     {
137         aOutVectorToLight = m_inv_direction;
138         aOutDistance      = std::numeric_limits<float>::infinity();
139         aOutLightColor    = m_color;
140     }
141 
142 private:
143     SFVEC3F m_inv_direction;        ///< opposite direction of the light
144     SFVEC3F m_color;                ///< light color
145 };
146 
147 
148 #endif // LIGHT_H
149