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/camera.h
22  * \brief Camera handling - CCamera class
23  */
24 
25 #pragma once
26 
27 #include "graphics/engine/engine.h"
28 
29 
30 class CObject;
31 class CRobotMain;
32 class CInput;
33 struct Event;
34 
35 
36 // Graphics module namespace
37 namespace Gfx
38 {
39 
40 
41 /**
42   \enum CameraType
43   \brief Type of camera */
44 enum CameraType
45 {
46     //! Undefined
47     CAM_TYPE_NULL = 0,
48     //! Free camera
49     CAM_TYPE_FREE,
50     //! Camera while editing a program
51     CAM_TYPE_EDIT,
52     //! Camera on board a robot
53     CAM_TYPE_ONBOARD,
54     //! Camera behind a robot
55     CAM_TYPE_BACK,
56     //! Static camera following robot
57     CAM_TYPE_FIX,
58     //! Camera steady after explosion
59     CAM_TYPE_EXPLO,
60     //! Camera during a cutscene
61     CAM_TYPE_SCRIPT,
62     //! Visit camera, rotates around given position
63     CAM_TYPE_VISIT,
64     //! Static camera height
65     CAM_TYPE_PLANE,
66 };
67 
68 enum CameraSmooth
69 {
70     //! Sharp
71     CAM_SMOOTH_NONE         = 0,
72     //! Normal
73     CAM_SMOOTH_NORM         = 1,
74     //! Hard
75     CAM_SMOOTH_HARD         = 2,
76 };
77 
78 enum CenteringPhase
79 {
80     CAM_PHASE_NULL         = 0,
81     CAM_PHASE_START        = 1,
82     CAM_PHASE_WAIT         = 2,
83     CAM_PHASE_STOP         = 3,
84 };
85 
86 enum CameraEffect
87 {
88     //! No effect
89     CAM_EFFECT_NULL         = 0,
90     //! Digging in
91     CAM_EFFECT_TERRAFORM    = 1,
92     //! Hard landing
93     CAM_EFFECT_CRASH        = 2,
94     //! Explosion
95     CAM_EFFECT_EXPLO        = 3,
96     //! Shot by an enemy
97     CAM_EFFECT_SHOT         = 4,
98     //! Vibration during construction
99     CAM_EFFECT_VIBRATION    = 5,
100     //! Overheated reactor
101     CAM_EFFECT_PET          = 6,
102 };
103 
104 enum CameraOverEffect
105 {
106     //! No effect
107     CAM_OVER_EFFECT_NULL           = 0,
108     //! Flash red
109     CAM_OVER_EFFECT_BLOOD          = 1,
110     //! White -> nothing
111     CAM_OVER_EFFECT_FADEIN_WHITE   = 2,
112     //! Nothing -> white
113     CAM_OVER_EFFECT_FADEOUT_WHITE  = 3,
114     //! Nothing -> blue
115     CAM_OVER_EFFECT_FADEOUT_BLACK  = 4,
116     //! Lightning
117     CAM_OVER_EFFECT_LIGHTNING      = 5,
118 };
119 
120 
121 /**
122   \class CCamera
123   \brief Camera moving in 3D scene
124 
125   This class manages everything related to animating the camera in 3D scene.
126   Calculated values are then passed to Gfx::CEngine.
127 */
128 class CCamera
129 {
130 public:
131     CCamera();
132     ~CCamera();
133 
134     //! Management of an event
135     bool        EventProcess(const Event &event);
136 
137     /**
138      * \brief Initializes the camera
139      * \param eye Initial eye position
140      * \param lookat Initial lookat position
141      * \param delay Time of the initial entry animation
142      */
143     void        Init(Math::Vector eye, Math::Vector lookat, float delay);
144 
145     //! Sets the object controlling the camera
146     void        SetControllingObject(CObject* object);
147     //! Gets the object controlling the camera
148     CObject*    GetControllingObject();
149 
150     //! Change the type of camera
151     void        SetType(CameraType type);
152     //! Get the type of the camera
153     CameraType  GetType();
154 
155     //! Set smoothing mode
156     void         SetSmooth(CameraSmooth type);
157     //! Get smoothing mode
158     CameraSmooth GetSmooth();
159 
160 
161     //! Returns the current point of view of the camera
162     void        GetCamera(Math::Vector &eye, Math::Vector &lookat);
163 
164     //! \name Visit camera management (CAM_TYPE_VISIT) - camera in this mode shows a position, constantly rotating around it
165     //@{
166     //! Start visit camera
167     void        StartVisit(Math::Vector goal, float dist);
168     //! Stop visit camera
169     void        StopVisit();
170     //@}
171 
172     //! \name Camera "centering" - moves the camera to show some happening action (e.g. sniffer sniffing)
173     //@{
174     //! Move camera to show happening action
175     bool        StartCentering(CObject *object, float angleH, float angleV, float dist, float time);
176     //! Go back to normal position after showing some happening action
177     bool        StopCentering(CObject *object, float time);
178     //! Abort centering animation in the current position
179     void        AbortCentering();
180     //@}
181 
182     //! \name Camera shake effects
183     //@{
184     //! Starts a camera shake effect
185     void        StartEffect(CameraEffect effect, Math::Vector pos, float force);
186     //! Removes the camera shake effect
187     void        FlushEffect();
188     //@}
189 
190     //! \name Camera overlay effects
191     //@{
192     //! Starts camera overlay effect
193     void        StartOver(CameraOverEffect effect, Math::Vector pos, float force);
194     //! Removes camera overlay effect
195     void        FlushOver();
196     //! Specifies camera overlay effect base color
197     void        SetOverBaseColor(Color color);
198     //@}
199 
200     //! \name Script camera - cutscenes controlled by external code
201     //@{
202     //! Script camera: Set camera position
203     void        SetScriptCamera(Math::Vector eye, Math::Vector lookat);
204     //! Script camera: Animate to given camera position
205     void        SetScriptCameraAnimate(Math::Vector eye, Math::Vector lookat);
206     //! Script camera: Animate to given eye position
207     void        SetScriptCameraAnimateEye(Math::Vector eye);
208     //! Script camera: Animate to given lookat position
209     void        SetScriptCameraAnimateLookat(Math::Vector lookat);
210     //@}
211 
212     //! \name Configuration settings
213     //@{
214     void        SetEffect(bool enable);
215     bool        GetEffect();
216     void        SetBlood(bool enable);
217     bool        GetBlood();
218     void        SetOldCameraScroll(bool scroll);
219     bool        GetOldCameraScroll();
220     void        SetCameraInvertX(bool invert);
221     bool        GetCameraInvertX();
222     void        SetCameraInvertY(bool invert);
223     bool        GetCameraInvertY();
224     //@}
225 
226     //! Temporarily freeze camera movement
227     void        SetFreeze(bool freeze);
228 
229     //! Set camera speed
230     void        SetCameraSpeed(float speed);
231 
232 protected:
233     //! Advances the effect of the camera
234     void        EffectFrame(const Event &event);
235     //! Advanced overlay effect in the foreground
236     void        OverFrame(const Event &event);
237 
238     bool        EventFrameFree(const Event &event, bool keysAllowed);
239     bool        EventFrameBack(const Event &event);
240     bool        EventFrameFix(const Event &event);
241     bool        EventFrameExplo(const Event &event);
242     bool        EventFrameOnBoard(const Event &event);
243     bool        EventFrameVisit(const Event &event);
244     bool        EventFrameScript(const Event &event);
245 
246     /**
247      * \brief Calculates camera animation and sends updated camera position to the 3D engine
248      * \param eyePt Eye point
249      * \param lookatPt Lookat point
250      * \param rTime Time since last time this function was called (used to calculate animation)
251      * \see SetViewParams
252      */
253     void        UpdateCameraAnimation(const Math::Vector &eyePt, const Math::Vector &lookatPt, float rTime);
254 
255     /**
256      * \brief Avoid the obstacles
257      *
258      * For CAM_TYPE_BACK: make obstacles transparent
259      * For CAM_TYPE_FIX or CAM_TYPE_PLANE: adjust eye not to hit the obstacles
260      *
261      * \param eye Eye position, may be adjusted
262      * \param lookat Lookat point
263      */
264     void        IsCollision(Math::Vector &eye, Math::Vector lookat);
265     //! Avoid the obstacles (CAM_TYPE_BACK)
266     void        IsCollisionBack();
267     //! Avoid the obstacles (CAM_TYPE_FIX or CAM_TYPE_PLANE)
268     void        IsCollisionFix(Math::Vector &eye, Math::Vector lookat);
269 
270     //! Adjusts the camera not to enter the ground
271     Math::Vector ExcludeTerrain(Math::Vector eye, Math::Vector lookat, float &angleH, float &angleV);
272     //! Adjusts the camera not to enter an object
273     Math::Vector ExcludeObject(Math::Vector eye, Math::Vector lookat, float &angleH, float &angleV);
274 
275     /**
276      * \brief Updates the location and direction of the camera in the 3D engine
277      * \param eye Eye point
278      * \param lookat Lookat point
279      * \param up Up vector
280      * \see CEngine::SetViewParams
281      */
282     void        SetViewParams(const Math::Vector &eye, const Math::Vector &lookat, const Math::Vector &up = Math::Vector(0.0f, 1.0f, 0.0f));
283 
284     /**
285      * \brief Calculate camera movement (from user inputs) to apply
286      * \return Math::Vector where x, y represent respectively horizontal and vertical angle change in radians and z represents zoom (distance change)
287      * \remarks Should not be called more often than once every EVENT_FRAME
288      **/
289     Math::Vector CalculateCameraMovement(const Event &event, bool keysAllowed = true);
290 
291 protected:
292     CEngine*     m_engine;
293     CRobotMain*  m_main;
294     CTerrain*    m_terrain;
295     CWater*      m_water;
296     CInput*      m_input;
297 
298     //! The type of camera
299     CameraType   m_type;
300     //! Type of smoothing
301     CameraSmooth m_smooth;
302     //! Object linked to the camera
303     CObject*     m_cameraObj;
304 
305     //! Remaining time of initial camera entry animation
306     float        m_initDelay;
307 
308     //! Current eye
309     Math::Vector    m_actualEye;
310     //! Current aim
311     Math::Vector    m_actualLookat;
312     //! Final eye
313     Math::Vector    m_finalEye;
314     //! Final lookat
315     Math::Vector    m_finalLookat;
316     //! Eye position at the moment of entering CAM_TYPE_INFO/CAM_TYPE_VISIT
317     Math::Vector    m_prevEye;
318     //! Lookat position at the moment of entering CAM_TYPE_INFO/CAM_TYPE_VISIT
319     Math::Vector    m_prevLookat;
320 
321     float            m_focus;
322 
323     //! CAM_TYPE_FREE: eye
324     Math::Vector    m_eyePt;
325     //! CAM_TYPE_FREE: horizontal direction
326     float       m_directionH;
327     //! CAM_TYPE_FREE: vertical direction
328     float       m_directionV;
329     //! CAM_TYPE_FREE: height above the ground
330     float       m_heightEye;
331     //! CAM_TYPE_FREE: height above the ground
332     float       m_heightLookat;
333     //! CAM_TYPE_FREE: speed of movement
334     float       m_speed;
335 
336     //! CAM_TYPE_BACK: distance
337     float       m_backDist;
338     //! CAM_TYPE_BACK: minimal distance
339     float       m_backMin;
340     //! CAM_TYPE_BACK: additional horizontal direction
341     float       m_addDirectionH;
342     //! CAM_TYPE_BACK: additional vertical direction
343     float       m_addDirectionV;
344 
345     //! CAM_TYPE_FIX: distance
346     float       m_fixDist;
347     //! CAM_TYPE_FIX: horizontal direction
348     float       m_fixDirectionH;
349     //! CAM_TYPE_FIX: vertical direction
350     float       m_fixDirectionV;
351 
352     //! CAM_TYPE_VISIT: target position
353     Math::Vector m_visitGoal;
354     //! CAM_TYPE_VISIT: distance
355     float        m_visitDist;
356     //! CAM_TYPE_VISIT: relative time
357     float        m_visitTime;
358     //! CAM_TYPE_VISIT: initial type
359     CameraType   m_visitType;
360     //! CAM_TYPE_VISIT: direction
361     float        m_visitDirectionV;
362 
363     //! Last known mouse position, used to calculate change since last frame
364     Math::Point  m_mousePos = Math::Point(0.5f, 0.5f);
365     //! Change of mouse position since last frame
366     Math::Point  m_mouseDelta = Math::Point(0.0f, 0.0f);
367     //! Change of camera position caused by edge camera
368     Math::Point  m_mouseDeltaEdge = Math::Point(0.0f, 0.0f);
369     //! Change of mouse wheel since last frame
370     float        m_mouseWheelDelta = 0.0f;
371 
372     CenteringPhase m_centeringPhase;
373     float       m_centeringAngleH;
374     float       m_centeringAngleV;
375     float       m_centeringDist;
376     float       m_centeringCurrentH;
377     float       m_centeringCurrentV;
378     float       m_centeringTime;
379     float       m_centeringProgress;
380 
381     CameraEffect m_effectType;
382     Math::Vector m_effectPos;
383     float        m_effectForce;
384     float        m_effectProgress;
385     Math::Vector m_effectOffset;
386 
387     CameraOverEffect  m_overType;
388     float       m_overForce;
389     float       m_overTime;
390     Color  m_overColorBase;
391     Color  m_overColor;
392     int         m_overMode;
393     float       m_overFadeIn;
394     float       m_overFadeOut;
395 
396     Math::Vector m_scriptEye;
397     Math::Vector m_scriptLookat;
398 
399     //! Is camera frozen?
400     bool m_freeze = false;
401 
402     //! \name Configuration settings
403     //@{
404     bool        m_effect;
405     bool        m_blood;
406     bool        m_oldCameraScroll;
407     bool        m_cameraInvertX;
408     bool        m_cameraInvertY;
409     //@}
410 };
411 
412 
413 } // namespace Gfx
414