1 //
2 //  SuperTuxKart - a fun racing game with go-kart
3 //  Copyright (C) 2004-2015 Steve Baker <sjbaker1@airmail.net>
4 //  Copyright (C) 2006-2015 SuperTuxKart-Team, Steve Baker
5 //
6 //  This program is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU General Public License
8 //  as published by the Free Software Foundation; either version 3
9 //  of the License, or (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.  See the
14 //  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, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19 
20 #include "graphics/camera.hpp"
21 
22 #include "audio/sfx_manager.hpp"
23 #include "config/stk_config.hpp"
24 #include "config/user_config.hpp"
25 #include "graphics/camera_debug.hpp"
26 #include "graphics/camera_end.hpp"
27 #include "graphics/camera_fps.hpp"
28 #include "graphics/camera_normal.hpp"
29 #include "graphics/irr_driver.hpp"
30 #include "io/xml_node.hpp"
31 #include "karts/abstract_kart.hpp"
32 #include "karts/explosion_animation.hpp"
33 #include "karts/kart.hpp"
34 #include "karts/skidding.hpp"
35 #include "physics/btKart.hpp"
36 #include "race/race_manager.hpp"
37 #include "tracks/track.hpp"
38 #include "utils/aligned_array.hpp"
39 #include "utils/constants.hpp"
40 #include "utils/vs.hpp"
41 
42 #include "ISceneManager.h"
43 #include <algorithm>
44 #include <cmath>
45 
46 std::vector<Camera*> Camera::m_all_cameras;
47 Camera*              Camera::s_active_camera = NULL;
48 Camera::CameraType   Camera::m_default_type  = Camera::CM_TYPE_NORMAL;
49 
50 // ------------------------------------------------------------------------
51 /** Creates a new camera and adds it to the list of all cameras. Also the
52  *  camera index (which determines which viewport to use in split screen)
53  *  is set.
54  */
createCamera(AbstractKart * kart,const int index)55 Camera* Camera::createCamera(AbstractKart* kart, const int index)
56 {
57 
58     Camera *camera = createCamera(index, m_default_type, kart);
59     m_all_cameras.push_back(camera);
60     std::sort(m_all_cameras.begin(), m_all_cameras.end(),
61         [](const Camera* a, const Camera* b)
62         {
63             return a->getIndex() < b->getIndex();
64         });
65     return camera;
66 }   // createCamera(kart)
67 
68 // ----------------------------------------------------------------------------
69 /** Creates a camera of the specified type, but does not add it to the list
70  *  of all cameras. This is a helper function for other static functions.
71  *  \paran index Index this camera has in the list of all cameras.
72  *  \param type The camera type of the camera to create.
73  *  \param kart To which kart the camera is attached (NULL if a free camera).
74  */
createCamera(unsigned int index,CameraType type,AbstractKart * kart)75 Camera* Camera::createCamera(unsigned int index, CameraType type,
76                              AbstractKart* kart)
77 {
78     Camera *camera = NULL;
79     switch (type)
80     {
81     case CM_TYPE_NORMAL: camera = new CameraNormal(CM_TYPE_NORMAL, index, kart);
82                                                                  break;
83     case CM_TYPE_DEBUG:  camera = new CameraDebug (index, kart); break;
84     case CM_TYPE_FPS:    camera = new CameraFPS   (index, kart); break;
85     case CM_TYPE_END:    camera = new CameraEnd   (index, kart); break;
86     }   // switch type
87 
88     return camera;
89 }   // createCamera
90 
91 // ----------------------------------------------------------------------------
changeCamera(unsigned int camera_index,CameraType type)92 void Camera::changeCamera(unsigned int camera_index, CameraType type)
93 {
94     assert(camera_index<m_all_cameras.size());
95 
96     Camera *old_camera = m_all_cameras[camera_index];
97     // Nothing to do if this is already the right type.
98 
99     if(old_camera->getType()==type) return;
100 
101     Camera *new_camera = createCamera(old_camera->getIndex(), type,
102                                       old_camera->m_original_kart);
103     // Replace the previous camera
104     m_all_cameras[camera_index] = new_camera;
105     if(s_active_camera == old_camera)
106         s_active_camera = new_camera;
107     delete old_camera;
108 }   // changeCamera
109 
110 // ----------------------------------------------------------------------------
resetAllCameras()111 void Camera::resetAllCameras()
112 {
113     for (unsigned int i = 0; i < Camera::getNumCameras(); i++)
114     {
115         changeCamera(i, m_default_type);
116         getCamera(i)->reset();
117     }
118 }   // resetAllCameras
119 
120 // ----------------------------------------------------------------------------
Camera(CameraType type,int camera_index,AbstractKart * kart)121 Camera::Camera(CameraType type, int camera_index, AbstractKart* kart)
122       : m_kart(NULL)
123 {
124     m_mode          = CM_NORMAL;
125     m_type          = type;
126     m_index         = camera_index;
127     m_original_kart = kart;
128     m_camera        = irr_driver->addCameraSceneNode();
129     m_previous_pv_matrix = core::matrix4();
130 
131     setupCamera();
132     setKart(kart);
133     m_ambient_light = Track::getCurrentTrack()->getDefaultAmbientColor();
134 
135     reset();
136 }   // Camera
137 
138 // ----------------------------------------------------------------------------
139 /** Removes the camera scene node from the scene.
140  */
~Camera()141 Camera::~Camera()
142 {
143     irr_driver->removeCameraSceneNode(m_camera);
144 
145     if (s_active_camera == this)
146         s_active_camera = NULL;
147 }   // ~Camera
148 
149 //-----------------------------------------------------------------------------
150 /** Changes the owner of this camera to the new kart.
151  *  \param new_kart The new kart to use this camera.
152  */
setKart(AbstractKart * new_kart)153 void Camera::setKart(AbstractKart *new_kart)
154 {
155     m_kart = new_kart;
156 #ifdef DEBUG
157     std::string name = new_kart ? new_kart->getIdent()+"'s camera"
158                                 : "Unattached camera";
159     getCameraSceneNode()->setName(name.c_str());
160 #endif
161 
162 }   // setKart
163 
164 //-----------------------------------------------------------------------------
165 /** Sets up the viewport, aspect ratio, field of view, and scaling for this
166  *  camera.
167  */
setupCamera()168 void Camera::setupCamera()
169 {
170     m_viewport = irr_driver->getSplitscreenWindow(m_index);
171     m_aspect = (float)((float)(m_viewport.getWidth()) / (float)(m_viewport.getHeight()));
172 
173     m_scaling = core::vector2df(
174         float(irr_driver->getActualScreenSize().Width) / m_viewport.getWidth() ,
175         float(irr_driver->getActualScreenSize().Height) / m_viewport.getHeight());
176 
177     if (RaceManager::get()->getNumLocalPlayers() > 1)
178     {
179         m_fov = DEGREE_TO_RAD * stk_config->m_camera_fov
180           [RaceManager::get()->getNumLocalPlayers() - 1];
181     }
182     else
183     {
184         m_fov = DEGREE_TO_RAD * UserConfigParams::m_camera_fov;
185     }
186 
187     m_camera->setFOV(m_fov);
188     m_camera->setAspectRatio(m_aspect);
189     m_camera->setFarValue(Track::getCurrentTrack()->getCameraFar());
190 }   // setupCamera
191 
192 // ----------------------------------------------------------------------------
193 /** Sets the mode of the camera.
194  *  \param mode Mode the camera should be switched to.
195  */
setMode(Mode mode)196 void Camera::setMode(Mode mode)
197 {
198     if (mode == m_mode) return;
199     // If we switch from reverse view, move the camera immediately to the
200     // correct position.
201     if( (m_mode==CM_REVERSE && mode==CM_NORMAL) ||
202         (m_mode==CM_FALLING && mode==CM_NORMAL)    )
203     {
204         Vec3 start_offset(0, 1.6f, -3);
205         Vec3 current_position = m_kart->getSmoothedTrans()(start_offset);
206         Vec3 target_position = m_kart->getSmoothedTrans()(Vec3(0, 0, 1));
207         // Don't set position and target the same, otherwise
208         // nan values will be calculated in ViewArea of camera
209         m_camera->setPosition(current_position.toIrrVector());
210         m_camera->setTarget(target_position.toIrrVector());
211     }
212 
213     m_previous_mode = m_mode;
214     m_mode = mode;
215 }   // setMode
216 
217 // ----------------------------------------------------------------------------
218 /** Returns the current mode of the camera.
219  */
getMode()220 Camera::Mode Camera::getMode()
221 {
222     return m_mode;
223 }   // getMode
224 
225 // ----------------------------------------------------------------------------
226 /** Returns the last kwown mode of the camera.
227  */
getPreviousMode()228 Camera::Mode Camera::getPreviousMode()
229 {
230     return m_previous_mode;
231 }   // getPreviousMode
232 
233 // ----------------------------------------------------------------------------
234 /** Returns true if camera is a spectator camera
235  */
isSpectatorMode()236 bool Camera::isSpectatorMode()
237 {
238     return ((m_mode == CM_SPECTATOR_TOP_VIEW) || (m_mode == CM_SPECTATOR_SOCCER));
239 }   // isSpectatorMode
240 
241 // ----------------------------------------------------------------------------
242 /** Switch to next spectator mode  (a -> soccer -> top view -> a)
243  */
setNextSpectatorMode()244 void Camera::setNextSpectatorMode()
245 {
246     if (m_mode == CM_SPECTATOR_SOCCER) m_mode = CM_SPECTATOR_TOP_VIEW;
247     else if (m_mode == CM_SPECTATOR_TOP_VIEW) m_mode = m_previous_mode;
248     else setMode(CM_SPECTATOR_SOCCER);
249 }   // setNextSpectatorMode
250 
251 //-----------------------------------------------------------------------------
252 /** Reset is called when a new race starts. Make sure that the camera
253     is aligned neutral, and not like in the previous race
254 */
reset()255 void Camera::reset()
256 {
257     m_kart = m_original_kart;
258     setMode(CM_NORMAL);
259 
260     if (m_kart != NULL)
261         setInitialTransform();
262 }   // reset
263 
264 //-----------------------------------------------------------------------------
265 /** Saves the current kart position as initial starting position for the
266  *  camera.
267  */
setInitialTransform()268 void Camera::setInitialTransform()
269 {
270     if (m_kart == NULL) return;
271     Vec3 start_offset(0, 1.6f, -3);
272     Vec3 current_position = m_kart->getSmoothedTrans()(start_offset);
273     assert(!std::isnan(current_position.getX()));
274     assert(!std::isnan(current_position.getY()));
275     assert(!std::isnan(current_position.getZ()));
276     m_camera->setPosition(  current_position.toIrrVector());
277     // Reset the target from the previous target (in case of a restart
278     // of a race) - otherwise the camera will initially point in the wrong
279     // direction till smoothMoveCamera has corrected this. Setting target
280     // to position doesn't make sense, but smoothMoves will adjust the
281     // value before the first frame is rendered
282     Vec3 target_position = m_kart->getSmoothedTrans()(Vec3(0, 0, 1));
283     m_camera->setTarget(target_position.toIrrVector());
284     m_camera->setRotation(core::vector3df(0, 0, 0));
285     m_camera->setFOV(m_fov);
286 }   // setInitialTransform
287 
288 //-----------------------------------------------------------------------------
289 /** Called once per time frame to move the camera to the right position.
290  *  \param dt Time step.
291  */
update(float dt)292 void Camera::update(float dt)
293 {
294     if (!m_kart)
295     {
296         if (RaceManager::get()->getNumLocalPlayers() < 2)
297         {
298             Vec3 pos(m_camera->getPosition());
299             SFXManager::get()->positionListener(pos,
300                 Vec3(m_camera->getTarget()) - pos,
301                 Vec3(0, 1, 0));
302         }
303 
304         return; // cameras not attached to kart must be positioned manually
305     }
306 
307     if (RaceManager::get()->getNumLocalPlayers() < 2)
308     {
309         Vec3 heading(sinf(m_kart->getHeading()), 0.0f, cosf(m_kart->getHeading()));
310         SFXManager::get()->positionListener(m_kart->getSmoothedXYZ(),
311                                             heading,
312                                             Vec3(0, 1, 0));
313     }
314 }   // update
315 
316 // ----------------------------------------------------------------------------
317 /** Sets viewport etc. for this camera. Called from irr_driver just before
318  *  rendering the view for this kart.
319  */
activate(bool alsoActivateInIrrlicht)320 void Camera::activate(bool alsoActivateInIrrlicht)
321 {
322     s_active_camera = this;
323     if (alsoActivateInIrrlicht)
324     {
325         irr::scene::ISceneManager *sm = irr_driver->getSceneManager();
326         sm->setActiveCamera(m_camera);
327         irr_driver->getVideoDriver()->setViewPort(m_viewport);
328     }
329 }   // activate
330 
331