Angel 3.2
A 2D Game Prototyping Engine
Camera.cpp
1 
2 // Copyright (C) 2008-2013, Shane Liesegang
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are met:
7 //
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 // * Neither the name of the copyright holder nor the names of any
14 // contributors may be used to endorse or promote products derived from
15 // this software without specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 // POSSIBILITY OF SUCH DAMAGE.
29 
30 #include "stdafx.h"
31 #include "../Infrastructure/Camera.h"
32 
33 #include "../Infrastructure/Common.h"
34 #include "../Infrastructure/World.h"
35 #include "../Util/MathUtil.h"
36 #include "../Messaging/Switchboard.h"
37 
38 #include <math.h>
39 
40 Camera *Camera::s_Camera = NULL;
41 
42 Camera::Camera()
43 {
44  Reset();
45 }
46 
48 {
49  if (s_Camera == NULL)
50  {
51  s_Camera = new Camera();
52  }
53  return *s_Camera;
54 }
55 
56 //destroy the singleton
58 {
59  delete s_Camera;
60  s_Camera = NULL;
61 }
62 
63 #if !ANGEL_MOBILE
64  void Camera::ResizeCallback(GLFWwindow* window, int w, int h)
65  {
66  theCamera.Resize(w, h);
67  }
68 #endif
69 
71 {
72  _aperture = 90.0f;
73  _camera3DPosition = Vector3(0.0f, 0.0f, 10.0f);
74  _view = Vector3(0.0f, 0.0f, -10.0f);
75  _up = Vector3(0.0f, 1.0f, 0.0);
76  _zNearClip = 0.001f;
77  _zFarClip = 200.f;
78  _locked = NULL;
79 }
80 
81 void Camera::LockTo(Actor *locked, bool lockX, bool lockY, bool lockRotation)
82 {
83  _locked = locked;
84  _lockX = lockX;
85  _lockY = lockY;
86  _lockRotation = lockRotation;
87 }
88 
89 void Camera::Resize(int width, int height)
90 {
91  if ( (_windowHeight != height) || (_windowWidth != width) )
92  {
93  _windowHeight = height;
94  _windowWidth = width;
95 
96  glViewport(0, 0, _windowWidth, _windowHeight);
97  }
98 
99  glMatrixMode(GL_PROJECTION);
100  glLoadIdentity();
101  float aspect = (float)_windowWidth/(float)_windowHeight;
102  gluPerspective(_aperture, aspect, _zNearClip, _zFarClip);
103  glMatrixMode(GL_MODELVIEW);
104 
105  theSwitchboard.Broadcast(new Message("CameraChange"));
106 }
107 
108 const int Camera::GetWindowHeight() const
109 {
110  return _windowHeight;
111 }
112 
113 const int Camera::GetWindowWidth() const
114 {
115  return _windowWidth;
116 }
117 
118 const double Camera::GetViewRadius() const
119 {
120  double sideAngle = MathUtil::ToRadians(_aperture / 2.0);
121  return tan(sideAngle) * fabs(_camera3DPosition.Z);
122 }
123 
125 {
127 }
128 
130 {
132 }
133 
134 void Camera::Update(float dt)
135 {
136  Actor::Update(dt);
137 
138  if (_locked != NULL)
139  {
140  bool change = false;
141  Vector2 pos = _locked->GetPosition();
142  if (_lockX && !MathUtil::FuzzyEquals(_camera3DPosition.X, pos.X))
143  {
144  _camera3DPosition.X = pos.X;
145  change = true;
146  }
147  if (_lockY && !MathUtil::FuzzyEquals(_camera3DPosition.Y, pos.Y))
148  {
149  _camera3DPosition.Y = pos.Y;
150  change = true;
151  }
152  if (_lockRotation && !MathUtil::FuzzyEquals(_rotation, _locked->GetRotation()))
153  {
154  _rotation = _locked->GetRotation();
155  change = true;
156  }
157  if (change)
158  {
159  theSwitchboard.Broadcast(new Message("CameraChange"));
160  }
161  }
162  else
163  {
164  if (_3dPositionInterval.ShouldStep())
165  {
166  SetPosition(_3dPositionInterval.Step(dt));
167  if (!_3dPositionInterval.ShouldStep())
168  {
169  if (_3dPositionIntervalMessage != "")
170  {
171  theSwitchboard.Broadcast(new Message(_3dPositionIntervalMessage, this));
172  }
173  }
174  }
175  }
176 }
177 
179 {
180  /*
181  TODO Make this so it only updates if things have been dirtied.
182  */
183  glMatrixMode(GL_MODELVIEW);
184  glLoadIdentity();
185  glRotatef(_rotation, 0.0f, 0.0f, 1.0f);
186  gluLookAt(_camera3DPosition.X, _camera3DPosition.Y, _camera3DPosition.Z,
187  _camera3DPosition.X + _view.X,
188  _camera3DPosition.Y + _view.Y,
189  _camera3DPosition.Z + _view.Z,
190  _up.X, _up.Y, _up.Z
191  );
192 }
193 
194 void Camera::SetPosition(float x, float y, float z)
195 {
196  _camera3DPosition = Vector3(x, y, z);
197  theSwitchboard.Broadcast(new Message("CameraChange"));
198 }
199 
200 void Camera::SetPosition(float x, float y)
201 {
202  _camera3DPosition = Vector3(x, y, _camera3DPosition.Z);
203  _position = Vector2(_camera3DPosition.X, _camera3DPosition.Y);
204  theSwitchboard.Broadcast(new Message("CameraChange"));
205 }
206 
208 {
209  _camera3DPosition = Vector3(v2.X, v2.Y, _camera3DPosition.Z);
210  _position = Vector2(_camera3DPosition.X, _camera3DPosition.Y);
211  theSwitchboard.Broadcast(new Message("CameraChange"));
212 }
213 
215 {
216  _camera3DPosition = v3;
217  _position = Vector2(_camera3DPosition.X, _camera3DPosition.Y);
218  theSwitchboard.Broadcast(new Message("CameraChange"));
219 }
220 
221 void Camera::MoveTo(const Vector3& newPosition, float duration, bool smooth, String onCompletionMessage)
222 {
223  _3dPositionInterval = Interval<Vector3>(_camera3DPosition, newPosition, duration, smooth);
224  _3dPositionIntervalMessage = onCompletionMessage;
225 }
226 
228 {
229  return Vector2(_camera3DPosition.X, _camera3DPosition.Y);
230 }
231 
232 float Camera::GetZ() const
233 {
234  return _camera3DPosition.Z;
235 }
236 
237 void Camera::SetRotation(float newRotation)
238 {
239  Actor::SetRotation(newRotation);
240  theSwitchboard.Broadcast(new Message("CameraChange"));
241 }
242 
243 float Camera::GetZForViewRadius(float radius)
244 {
245  double sideAngle = MathUtil::ToRadians(_aperture / 2.0);
246  return radius / tan(sideAngle);
247 }
248 
250 {
251  return _zNearClip;
252 }
253 
255 {
256  return _zFarClip;
257 }
258 
259 void Camera::SetZByViewRadius(float newRadius)
260 {
261  double sideAngle = MathUtil::ToRadians(_aperture / 2.0);
262  _camera3DPosition.Z = newRadius / tan(sideAngle);
263 }
264 
265 void Camera::SetNearClipDist(float dist)
266 {
267  _zNearClip = dist;
268  Resize(_windowWidth, _windowHeight);
269 }
270 
271 void Camera::SetFarClipDist(float dist)
272 {
273  _zFarClip = dist;
274  Resize(_windowWidth, _windowHeight);
275 }
276 
277 void Camera::SetViewCenter(float x, float y, float z)
278 {
279  _view = Vector3(x, y, z);
280  theSwitchboard.Broadcast(new Message("CameraChange"));
281 }
282 
284 {
285  return _view;
286 }
287