1 /*
2  * This file is part of the Colobot: Gold Edition source code
3  * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam
4  * http://epsitec.ch; http://colobot.info; http://github.com/colobot
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14  * See the GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see http://gnu.org/licenses
18  */
19 
20 /**
21  * \file graphics/engine/lightman.h
22  * \brief Dynamic light manager - CLightManager class
23  */
24 
25 #pragma once
26 
27 #include "graphics/core/light.h"
28 
29 #include "graphics/engine/engine.h"
30 
31 #include "math/vector.h"
32 
33 
34 // Graphics module namespace
35 namespace Gfx
36 {
37 
38 struct Color;
39 
40 /**
41  * \struct LightProgression
42  * \brief Describes the progression of light parameters change
43  */
44 struct LightProgression
45 {
46     //! Starting value
47     float   starting;
48     //! Ending (destination) value
49     float   ending;
50     //! Current value
51     float   current;
52     //! Progress from start to end
53     float   progress;
54     //! Speed of progression
55     float   speed;
56 
LightProgressionLightProgression57     LightProgression()
58      : starting(0.0f)
59      , ending(0.0f)
60      , current(0.0f)
61      , progress(0.0f)
62      , speed(0.0f)
63     {}
64 
65     //! Initializes the progression
66     void Init(float value);
67 
68     //! Updates the progression
69     void Update(float rTime);
70 
71     //! Sets the new end value (starting is set to current)
72     void SetTarget(float value);
73 };
74 
75 /**
76  * \enum LightPriority
77  * \brief Priority in light assignment
78  */
79 enum LightPriority
80 {
81     LIGHT_PRI_HIGHEST = 0, //!< always highest weight (always picked)
82     LIGHT_PRI_HIGH = 1,    //!< high weight
83     LIGHT_PRI_LOW  = 2     //!< low weight
84 };
85 
86 /**
87  * \struct DynamicLight
88  * \brief Dynamic light in 3D scene
89  *
90  * It is an extension over standard light properties. Added are dynamic progressions for light
91  * colors and intensity and types of objects included/excluded in lighting.
92  */
93 struct DynamicLight
94 {
95     //! Rank (index)
96     int rank;
97 
98     //! Whether the light is used
99     bool used;
100     //! Whether the light is turned on
101     bool enabled;
102 
103     //! Priority in assignment
104     LightPriority priority;
105 
106     //! Configuration of the light
107     Light light;
108 
109     //! Progression of intensity [0, 1]
110     LightProgression intensity;
111     //! Progression of red diffuse color
112     LightProgression colorRed;
113     //! Progression of green diffuse color
114     LightProgression colorGreen;
115     //! Progression of blue diffuse color
116     LightProgression colorBlue;
117 
118     //! Type of objects included in lighting with this light; if ENG_OBJTYPE_NULL is used, it is ignored
119     EngineObjectType includeType;
120     //! Type of objects excluded from lighting with this light; if ENG_OBJTYPE_NULL is used, it is ignored
121     EngineObjectType excludeType;
122 
DynamicLightDynamicLight123     DynamicLight()
124      : rank(0)
125      , used(false)
126      , enabled(false)
127      , priority(LIGHT_PRI_LOW)
128      , includeType(ENG_OBJTYPE_NULL)
129      , excludeType(ENG_OBJTYPE_NULL)
130     {}
131 };
132 
133 /**
134  * \class CLightManager
135  * \brief Manager for dynamic lights in 3D scene
136  *
137  * The class is responsible for managing dynamic lights (struct DynamicLight) used in 3D scene.
138  * The dynamic lights are created, updated and deleted through the class' interface.
139  *
140  * Since there is a limit on total number of lights available in OpenGL (usually up to 8), the dynamic lights
141  * must be emulated by displaying only some of them. All functions normally operate only on DynamicLight structs,
142  * updating the models with new values, while only one function, UpdateDeviceLights(), performs the actual
143  * synchronization to the device. It allocates device's light slots as necessary, with two priority levels
144  * for lights.
145  */
146 class CLightManager
147 {
148 public:
149     //! Constructor
150     CLightManager(CEngine* engine);
151     //! Destructor
152     virtual ~CLightManager();
153 
154     //! Sets the device to be used
155     void            SetDevice(CDevice* device);
156 
157     //! Prints debug info
158     void DebugDumpLights();
159 
160     //! Clears and disables all lights
161     void            FlushLights();
162     //! Creates a new dynamic light and returns its index (lightRank)
163     int             CreateLight(LightPriority priority = LIGHT_PRI_LOW);
164     //! Deletes and disables the given dynamic light
165     bool            DeleteLight(int lightRank);
166     //! Sets the light parameters for dynamic light
167     bool            SetLight(int lightRank, const Light &light);
168     //! Returns the light parameters for given dynamic light
169     bool            GetLight(int lightRank, Light &light);
170     //! Enables/disables the given dynamic light
171     bool            SetLightEnabled(int lightRank, bool enabled);
172     //! Changes the light priority
173     bool            SetLightPriority(int lightRank, LightPriority priority);
174 
175     //! Sets what objects are included in given dynamic light
176     bool            SetLightIncludeType(int lightRank, EngineObjectType type);
177     //! Sets what objects are excluded from given dynamic light
178     bool            SetLightExcludeType(int lightRank, EngineObjectType type);
179 
180     //! Sets the position of dynamic light
181     bool            SetLightPos(int lightRank, const Math::Vector &pos);
182     //! Returns the position of dynamic light
183     Math::Vector    GetLightPos(int lightRank);
184 
185     //! Sets the direction of dynamic light
186     bool            SetLightDir(int lightRank, const Math::Vector &dir);
187     //! Returns the direction of dynamic light
188     Math::Vector    GetLightDir(int lightRank);
189 
190     //! Sets the destination intensity for dynamic light's intensity progression
191     bool            SetLightIntensity(int lightRank, float value);
192     //! Returns the current light intensity
193     float           GetLightIntensity(int lightRank);
194     //! Sets the rate of change for dynamic light intensity
195     bool            SetLightIntensitySpeed(int lightRank, float speed);
196 
197     //! Adjusts the color of all dynamic lights
198     void            AdaptLightColor(const Color &color, float factor);
199 
200     //! Sets the destination color for dynamic light's color progression
201     bool            SetLightColor(int lightRank, const Color &color);
202     //! Returns current light color
203     Color           GetLightColor(int lightRank);
204     //! Sets the rate of change for dynamic light colors (RGB)
205     bool            SetLightColorSpeed(int lightRank, float speed);
206 
207     //! Updates progression of dynamic lights
208     void            UpdateProgression(float rTime);
209     //! Updates (recalculates) all dynamic lights
210     void            UpdateLights();
211     //! Enables or disables dynamic lights affecting the given object type
212     void            UpdateDeviceLights(EngineObjectType type);
213 
214 protected:
215     class CLightsComparator
216     {
217         public:
218             CLightsComparator(Math::Vector eyePos, EngineObjectType objectType);
219 
220             bool operator()(const DynamicLight& left, const DynamicLight& right);
221 
222         private:
223             float GetLightWeight(const DynamicLight& dynLight);
224 
225             Math::Vector m_eyePos;
226             EngineObjectType m_objectType;
227     };
228 
229 protected:
230     CEngine*          m_engine;
231     CDevice*          m_device;
232 
233     //! Current time
234     float             m_time;
235     //! List of dynamic lights
236     std::vector<DynamicLight> m_dynLights;
237     //! Map of current light allocation: graphics light -> dynamic light
238     std::vector<int>  m_lightMap;
239 };
240 
241 } // namespace Gfx
242 
243