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