UFO: Alien Invasion
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
cl_camera.cpp
Go to the documentation of this file.
1 
5 /*
6 All original material Copyright (C) 2002-2020 UFO: Alien Invasion.
7 
8 Original file from Quake 2 v3.21: quake2-2.31/client/cl_input.c
9 Copyright (C) 1997-2001 Id Software, Inc.
10 
11 This program is free software; you can redistribute it and/or
12 modify it under the terms of the GNU General Public License
13 as published by the Free Software Foundation; either version 2
14 of the License, or (at your option) any later version.
15 
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 
20 See the GNU General Public License for more details.
21 
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 
26 */
27 
28 #include "../client.h"
29 #include "cl_view.h"
30 #include "cl_hud.h"
31 #include "../input/cl_input.h"
32 #include "events/e_parse.h"
33 
34 static bool cameraRoute = false;
35 static int cameraRouteEnd;
37 static float routeDist;
38 
39 
40 const float MIN_ZOOM = 0.5;
41 #ifdef ANDROID
42 const float MAX_ZOOM = 16.0; /* Too far zoom will cause the game to run terribly slow on low-end devices */
43 #else
44 const float MAX_ZOOM = 32.0;
45 #endif
46 
47 #define MIN_CAMROT_SPEED 5
48 #define MIN_CAMROT_ACCEL 5
49 #define MAX_CAMROT_SPEED 1000
50 #define MAX_CAMROT_ACCEL 1000
51 #define MIN_CAMMOVE_SPEED 150
52 #define MIN_CAMMOVE_ACCEL 150
53 #define MAX_CAMMOVE_SPEED 3000
54 #define MAX_CAMMOVE_ACCEL 3000
55 #define LEVEL_MIN 0.05
56 #define LEVEL_SPEED 3.0
57 #define MIN_CAMZOOM_QUANT 0.05
58 #define MAX_CAMZOOM_QUANT 1.0
59 
70 
75 static inline void CL_ClampCamToMap (const float border)
76 {
77  if (cl.cam.origin[0] < cl.mapData->mapBox.getMinX() - border)
78  cl.cam.origin[0] = cl.mapData->mapBox.getMinX() - border;
79  else if (cl.cam.origin[0] > cl.mapData->mapBox.getMaxX() + border)
80  cl.cam.origin[0] = cl.mapData->mapBox.getMaxX() + border;
81 
82  if (cl.cam.origin[1] < cl.mapData->mapBox.getMinY() - border)
83  cl.cam.origin[1] = cl.mapData->mapBox.getMinY() - border;
84  else if (cl.cam.origin[1] > cl.mapData->mapBox.getMaxY() + border)
85  cl.cam.origin[1] = cl.mapData->mapBox.getMaxY() + border;
86 }
87 
93 void CL_CameraMove (void)
94 {
95  if (cls.state != ca_active)
96  return;
97 
99  return;
100 
101  /* get relevant variables */
102  const float rotspeed =
103  (cl_camrotspeed->value > MIN_CAMROT_SPEED) ? ((cl_camrotspeed->value < MAX_CAMROT_SPEED) ? cl_camrotspeed->value : MAX_CAMROT_SPEED) : MIN_CAMROT_SPEED;
104  const float movespeed =
105  (cl_cammovespeed->value > MIN_CAMMOVE_SPEED) ?
106  ((cl_cammovespeed->value < MAX_CAMMOVE_SPEED) ? cl_cammovespeed->value / cl.cam.zoom : MAX_CAMMOVE_SPEED / cl.cam.zoom) : MIN_CAMMOVE_SPEED / cl.cam.zoom;
107  const float moveaccel =
108  (cl_cammoveaccel->value > MIN_CAMMOVE_ACCEL) ?
109  ((cl_cammoveaccel->value < MAX_CAMMOVE_ACCEL) ? cl_cammoveaccel->value / cl.cam.zoom : MAX_CAMMOVE_ACCEL / cl.cam.zoom) : MIN_CAMMOVE_ACCEL / cl.cam.zoom;
110 
111  /* calculate camera omega */
112  /* stop acceleration */
113  float frac = cls.frametime * moveaccel * 2.5;
114 
115  for (int i = 0; i < 2; i++) {
116  if (fabs(cl.cam.omega[i]) > frac) {
117  if (cl.cam.omega[i] > 0)
118  cl.cam.omega[i] -= frac;
119  else
120  cl.cam.omega[i] += frac;
121  } else
122  cl.cam.omega[i] = 0;
123 
124  /* rotational acceleration */
125  if (i == YAW)
126  cl.cam.omega[i] += CL_GetKeyMouseState(STATE_ROT) * frac * 2;
127  else
128  cl.cam.omega[i] += CL_GetKeyMouseState(STATE_TILT) * frac * 2;
129 
130  if (cl.cam.omega[i] > rotspeed)
131  cl.cam.omega[i] = rotspeed;
132  if (-cl.cam.omega[i] > rotspeed)
133  cl.cam.omega[i] = -rotspeed;
134  }
135 
136  cl.cam.omega[ROLL] = 0;
137  /* calculate new camera angles for this frame */
139 
140  if (cl.cam.angles[PITCH] > cl_campitchmax->value)
141  cl.cam.angles[PITCH] = cl_campitchmax->value;
142  if (cl.cam.angles[PITCH] < cl_campitchmin->value)
143  cl.cam.angles[PITCH] = cl_campitchmin->value;
144 
146 
147  /* camera route overrides user input */
148  vec3_t delta;
149  if (cameraRouteEnd > 0) {
150  if (cameraRouteEnd <= cl.time) {
152  cameraRouteEnd = 0;
153  } else {
154  return;
155  }
156  } else if (cameraRoute) {
157  /* camera route */
158  frac = cls.frametime * moveaccel * 2;
161  VectorNormalize2(cl.cam.speed, delta);
162  if (DotProduct(delta, routeDelta) < 0.05) {
163  cameraRoute = false;
164  cameraRouteEnd = cl.time + 500;
165  }
166  } else {
168  }
169  } else {
170  /* normal camera movement */
171  /* calculate ground-based movement vectors */
172  const float angle = cl.cam.angles[YAW] * torad;
173  const float sy = sin(angle);
174  const float cy = cos(angle);
175  vec3_t g_forward, g_right;
176 
177  VectorSet(g_forward, cy, sy, 0.0);
178  VectorSet(g_right, sy, -cy, 0.0);
179 
180  /* calculate camera speed */
181  /* stop acceleration */
182  frac = cls.frametime * moveaccel;
183  if (VectorLength(cl.cam.speed) > frac) {
184  VectorNormalize2(cl.cam.speed, delta);
185  VectorMA(cl.cam.speed, -frac, delta, cl.cam.speed);
186  } else {
188  }
189 
190  /* acceleration */
191  frac = cls.frametime * moveaccel * 3.5;
192  VectorClear(delta);
193  VectorScale(g_forward, CL_GetKeyMouseState(STATE_FORWARD), delta);
194  VectorMA(delta, CL_GetKeyMouseState(STATE_RIGHT), g_right, delta);
195  VectorNormalize(delta);
196  VectorMA(cl.cam.speed, frac, delta, cl.cam.speed);
197 
198  /* lerp the level change */
203  } else if (cl.cam.lerplevel > cl_worldlevel->value) {
207  }
208  }
209 
210  /* clamp speed */
211  frac = VectorLength(cl.cam.speed) / movespeed;
212  if (frac > 1.0)
213  VectorScale(cl.cam.speed, 1.0 / frac, cl.cam.speed);
214 
215  /* zoom change */
217  if (frac > 0.1) {
218  cl.cam.zoom *= 1.0 + cls.frametime * cl_camzoomspeed->value * frac;
219  /* ensure zoom isn't greater than either MAX_ZOOM or cl_camzoommax */
220  cl.cam.zoom = std::min(std::min(MAX_ZOOM, cl_camzoommax->value), cl.cam.zoom);
221  } else if (frac < -0.1) {
222  cl.cam.zoom /= 1.0 - cls.frametime * cl_camzoomspeed->value * frac;
223  /* ensure zoom isn't less than either MIN_ZOOM or cl_camzoommin */
224  cl.cam.zoom = std::max(std::max(MIN_ZOOM, cl_camzoommin->value), cl.cam.zoom);
225  }
227 
228  /* calc new camera reference and new camera real origin */
230  cl.cam.origin[2] = 0.;
231  if (cl_isometric->integer) {
232  CL_ClampCamToMap(72.);
235  } else {
236  const double border = 144.0 * (cl.cam.zoom - cl_camzoommin->value - 0.4) / cl_camzoommax->value;
237  CL_ClampCamToMap(std::min(border, 86.0));
240  }
241 }
242 
250 void CL_CameraRoute (const pos3_t from, const pos3_t target)
251 {
252  if (!cl_centerview->integer)
253  return;
254 
255  vec3_t targetCamera;
256  PosToVec(target, targetCamera);
257  const bool closeEnough = VectorCompareEps(targetCamera, cl.cam.origin, UNIT_SIZE);
258  if (closeEnough)
259  return;
260 
261  /* initialize the camera route variables */
262  PosToVec(from, routeFrom);
263  PosToVec(target, routeDelta);
265  routeDelta[2] = 0;
268 
269  /* center the camera on the route starting position */
271  /* set the world level to the z axis value of the camera target
272  * the camera lerp will do a smooth translate from the old level
273  * to the new one */
274  Cvar_SetValue("cl_worldlevel", target[2]);
275 
277  cameraRoute = true;
278 
280 }
281 
285 void CL_CheckCameraRoute (const pos3_t from, const pos3_t target)
286 {
287  pos3_t current;
288  VecToPos(cl.cam.origin, current);
289  const float minDistToMove = 4.0f;
290  const float dist = Vector2Dist(target, current);
291  if (dist < minDistToMove) {
292  if (target[2] != current[2])
293  Cvar_SetValue("cl_worldlevel", target[2]);
294  return;
295  }
296  CL_CameraRoute(from, target);
297 }
298 
302 void CL_CameraZoomIn (void)
303 {
304  float quant;
305 
306  /* check zoom quant */
307  if (cl_camzoomquant->value < MIN_CAMZOOM_QUANT)
308  quant = 1 + MIN_CAMZOOM_QUANT;
309  else if (cl_camzoomquant->value > MAX_CAMZOOM_QUANT)
310  quant = 1 + MAX_CAMZOOM_QUANT;
311  else
312  quant = 1 + cl_camzoomquant->value;
313 
314  /* change zoom */
315  cl.cam.zoom *= quant;
316 
317  /* ensure zoom doesn't exceed either MAX_ZOOM or cl_camzoommax */
318  cl.cam.zoom = std::min(std::min(MAX_ZOOM, cl_camzoommax->value), cl.cam.zoom);
320 }
321 
325 void CL_CameraZoomOut (void)
326 {
327  float quant;
328 
329  /* check zoom quant */
330  if (cl_camzoomquant->value < MIN_CAMZOOM_QUANT)
331  quant = 1 + MIN_CAMZOOM_QUANT;
332  else if (cl_camzoomquant->value > MAX_CAMZOOM_QUANT)
333  quant = 1 + MAX_CAMZOOM_QUANT;
334  else
335  quant = 1 + cl_camzoomquant->value;
336 
337  /* change zoom */
338  cl.cam.zoom /= quant;
339 
340  /* ensure zoom isnt less than either MIN_ZOOM or cl_camzoommin */
341  cl.cam.zoom = std::max(std::max(MIN_ZOOM, cl_camzoommin->value), cl.cam.zoom);
343 }
344 
345 #ifdef DEBUG
346 
351 static void CL_CamPrintAngles_f (void)
352 {
353  Com_Printf("camera angles %0.3f:%0.3f:%0.3f\n", cl.cam.angles[0], cl.cam.angles[1], cl.cam.angles[2]);
354 }
355 #endif /* DEBUG */
356 
357 static void CL_CamSetAngles_f (void)
358 {
359  const int c = Cmd_Argc();
360 
361  if (c < 3) {
362  Com_Printf("Usage %s <value> <value>\n", Cmd_Argv(0));
363  return;
364  }
365 
366  cl.cam.angles[PITCH] = atof(Cmd_Argv(1));
367  cl.cam.angles[YAW] = atof(Cmd_Argv(2));
368  cl.cam.angles[ROLL] = 0.0f;
369 }
370 
371 static void CL_CamSetZoom_f (void)
372 {
373  const int c = Cmd_Argc();
374 
375  if (c < 2) {
376  Com_Printf("Usage %s <value>\n", Cmd_Argv(0));
377  return;
378  }
379 
380  Com_Printf("old zoom value: %.2f\n", cl.cam.zoom);
381  cl.cam.zoom = atof(Cmd_Argv(1));
382  cl.cam.zoom = std::min(std::min(MAX_ZOOM, cl_camzoommax->value), cl.cam.zoom);
383  cl.cam.zoom = std::max(std::max(MIN_ZOOM, cl_camzoommin->value), cl.cam.zoom);
384 }
385 
386 static void CL_CenterCameraIntoMap_f (void)
387 {
389 }
390 
391 void CL_CameraInit (void)
392 {
393  cl_camrotspeed = Cvar_Get("cl_camrotspeed", "250", CVAR_ARCHIVE, "Rotation speed of the battlescape camera.");
394  cl_cammovespeed = Cvar_Get("cl_cammovespeed", "450", CVAR_ARCHIVE, "Movement speed of the battlescape camera.");
395  cl_cammoveaccel = Cvar_Get("cl_cammoveaccel", "1250", CVAR_ARCHIVE, "Movement acceleration of the battlescape camera.");
396  cl_campitchmax = Cvar_Get("cl_campitchmax", "89", 0, "Max. battlescape camera pitch - over 90 presents apparent mouse inversion.");
397  cl_camzoomspeed = Cvar_Get("cl_camzoomspeed", "2.0", 0);
398  cl_campitchmin = Cvar_Get("cl_campitchmin", "10", 0, "Min. battlescape camera pitch - under 35 presents difficulty positioning cursor.");
399  cl_camzoomquant = Cvar_Get("cl_camzoomquant", "0.16", CVAR_ARCHIVE, "Battlescape camera zoom quantisation.");
400  cl_camzoommin = Cvar_Get("cl_camzoommin", "0.3", 0, "Minimum zoom value for tactical missions.");
401  cl_camzoommax = Cvar_Get("cl_camzoommax", "3.4", 0, "Maximum zoom value for tactical missions.");
402  cl_centerview = Cvar_Get("cl_centerview", "1", CVAR_ARCHIVE, "Center the view when selecting a new soldier.");
403 
404 #ifdef DEBUG
405  Cmd_AddCommand("debug_camangles", CL_CamPrintAngles_f, "Print current camera angles.");
406 #endif /* DEBUG */
407  Cmd_AddCommand("camsetangles", CL_CamSetAngles_f, "Set camera angles to the given values.");
408  Cmd_AddCommand("camsetzoom", CL_CamSetZoom_f, "Set camera zoom level.");
409  Cmd_AddCommand("centercamera", CL_CenterCameraIntoMap_f, "Center camera on the map.");
410 }
#define CAMERA_START_DIST
Definition: cl_camera.h:43
float getMaxX() const
Definition: aabb.h:131
vec_t VectorLength(const vec3_t v)
Calculate the length of a vector.
Definition: mathlib.cpp:434
void CL_CameraMove(void)
Update the camera position. This can be done in two different reasons. The first is the user input...
Definition: cl_camera.cpp:93
const char * Cmd_Argv(int arg)
Returns a given argument.
Definition: cmd.cpp:516
#define CAMERA_START_HEIGHT
Definition: cl_camera.h:44
void Cmd_AddCommand(const char *cmdName, xcommand_t function, const char *desc)
Add a new command to the script interface.
Definition: cmd.cpp:744
#define VectorCopy(src, dest)
Definition: vector.h:51
static cvar_t * cl_campitchmax
Definition: cl_camera.cpp:64
#define STATE_ROT
Definition: cl_input.h:42
int viewHeight
Definition: cl_video.h:76
#define VectorSet(v, x, y, z)
Definition: vector.h:59
#define MIN_CAMMOVE_ACCEL
Definition: cl_camera.cpp:52
const float MIN_ZOOM
Definition: cl_camera.cpp:40
#define LEVEL_SPEED
Definition: cl_camera.cpp:56
void VectorMA(const vec3_t veca, const float scale, const vec3_t vecb, vec3_t outVector)
Sets vector_out (vc) to vevtor1 (va) + scale * vector2 (vb)
Definition: mathlib.cpp:261
cvar_t * cl_camzoomquant
Definition: cl_camera.cpp:67
#define ROLL
Definition: mathlib.h:56
static void CL_CamSetZoom_f(void)
Definition: cl_camera.cpp:371
This is a cvar definition. Cvars can be user modified and used in our menus e.g.
Definition: cvar.h:71
static float routeDist
Definition: cl_camera.cpp:37
#define STATE_TILT
Definition: cl_input.h:43
void CL_BlockBattlescapeEvents(bool block)
Adds the ability to block battlescape event execution until something other is finished. E.g. camera movement.
Definition: e_parse.cpp:83
float value
Definition: cvar.h:80
viddef_t viddef
Definition: cl_video.cpp:34
float CL_GetKeyMouseState(int dir)
Definition: cl_input.cpp:546
#define VectorDist(a, b)
Definition: vector.h:69
cvar_t * cl_centerview
Definition: cl_camera.cpp:69
#define MAX_CAMMOVE_SPEED
Definition: cl_camera.cpp:53
vec_t VectorNormalize2(const vec3_t v, vec3_t out)
Calculated the normal vector for a given vec3_t.
Definition: mathlib.cpp:237
#define STATE_RIGHT
Definition: cl_input.h:40
void Com_Printf(const char *const fmt,...)
Definition: common.cpp:386
int integer
Definition: cvar.h:81
void CL_CheckCameraRoute(const pos3_t from, const pos3_t target)
Only moves the camera to the given target location if its not yet close enough.
Definition: cl_camera.cpp:285
#define VectorScale(in, scale, out)
Definition: vector.h:79
#define MAX_CAMZOOM_QUANT
Definition: cl_camera.cpp:58
#define CVAR_ARCHIVE
Definition: cvar.h:40
static cvar_t * cl_camrotspeed
Definition: cl_camera.cpp:60
#define YAW
Definition: mathlib.h:55
client_static_t cls
Definition: cl_main.cpp:83
void AngleVectors(const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up)
Create the rotation matrix in order to rotate something.
Definition: mathlib.cpp:631
cvar_t * cl_camzoommax
Definition: cl_camera.cpp:66
cvar_t * cl_worldlevel
Definition: cl_hud.cpp:46
#define DotProduct(x, y)
Returns the distance between two 3-dimensional vectors.
Definition: vector.h:44
float frametime
Definition: client.h:59
vec3_t origin
Definition: cl_camera.h:31
cvar_t * Cvar_Get(const char *var_name, const char *var_value, int flags, const char *desc)
Init or return a cvar.
Definition: cvar.cpp:342
#define STATE_ZOOM
Definition: cl_input.h:41
void CL_CameraZoomIn(void)
Zooms the scene of the battlefield in.
Definition: cl_camera.cpp:302
#define MIN_CAMROT_SPEED
Definition: cl_camera.cpp:47
static vec3_t routeFrom
Definition: cl_camera.cpp:36
int Cmd_Argc(void)
Return the number of arguments of the current command. "command parameter" will result in a argc of 2...
Definition: cmd.cpp:505
static cvar_t * cl_camzoomspeed
Definition: cl_camera.cpp:65
#define MAX_CAMMOVE_ACCEL
Definition: cl_camera.cpp:54
#define VecToPos(v, p)
Map boundary is +/- MAX_WORLD_WIDTH - to get into the positive area we add the possible max negative ...
Definition: mathlib.h:100
#define PosToVec(p, v)
Pos boundary size is +/- 128 - to get into the positive area we add the possible max negative value a...
Definition: mathlib.h:110
clientBattleScape_t cl
#define PITCH
Definition: mathlib.h:54
void CL_ViewCalcFieldOfViewX(void)
Calculates refdef's FOV_X. Should generally be called after any changes are made to the zoom level (v...
Definition: cl_view.cpp:189
static cvar_t * cl_campitchmin
Definition: cl_camera.cpp:63
float getMaxY() const
Definition: aabb.h:134
pos_t pos3_t[3]
Definition: ufotypes.h:58
cvar_t * cl_isometric
Definition: cl_input.cpp:77
void getCenter(vec3_t center) const
Calculates the center of the bounding box.
Definition: aabb.h:155
#define UNIT_SIZE
Definition: defines.h:121
#define VectorClear(a)
Definition: vector.h:55
#define Vector2Dist(a, b)
Definition: vector.h:70
const float MAX_ZOOM
Definition: cl_camera.cpp:44
static void CL_ClampCamToMap(const float border)
forces the camera to stay within the horizontal bounds of the map plus some border ...
Definition: cl_camera.cpp:75
float getMinY() const
Definition: aabb.h:122
void CL_CameraInit(void)
Definition: cl_camera.cpp:391
static void CL_CamSetAngles_f(void)
Definition: cl_camera.cpp:357
QGL_EXTERN GLint i
Definition: r_gl.h:113
int viewWidth
Definition: cl_video.h:76
#define STATE_FORWARD
Definition: cl_input.h:39
#define MAX_CAMROT_SPEED
Definition: cl_camera.cpp:49
vec_t VectorNormalize(vec3_t v)
Calculate unit vector for a given vec3_t.
Definition: mathlib.cpp:745
static int cameraRouteEnd
Definition: cl_camera.cpp:35
#define MIN_CAMMOVE_SPEED
Definition: cl_camera.cpp:51
vec3_t angles
Definition: cl_camera.h:34
float getMinX() const
Definition: aabb.h:119
static vec3_t routeDelta
Definition: cl_camera.cpp:36
HUD related routines.
vec_t vec3_t[3]
Definition: ufotypes.h:39
#define torad
Definition: mathlib.h:50
#define CAMERA_LEVEL_HEIGHT
Definition: cl_camera.h:45
vec3_t camorg
Definition: cl_camera.h:32
AABB mapBox
Definition: typedefs.h:351
int VectorCompareEps(const vec3_t v1, const vec3_t v2, float epsilon)
Compare two vectors that may have an epsilon difference but still be the same vectors.
Definition: mathlib.cpp:413
float zoom
Definition: cl_camera.h:39
connstate_t state
Definition: client.h:55
void CL_CameraRoute(const pos3_t from, const pos3_t target)
Interpolates the camera movement from the given start point to the given end point.
Definition: cl_camera.cpp:250
static cvar_t * cl_cammovespeed
Definition: cl_camera.cpp:61
void CL_CameraZoomOut(void)
Zooms the scene of the battlefield out.
Definition: cl_camera.cpp:325
#define MIN_CAMZOOM_QUANT
Definition: cl_camera.cpp:57
static void CL_CenterCameraIntoMap_f(void)
Definition: cl_camera.cpp:386
vec3_t omega
Definition: cl_camera.h:35
void Cvar_SetValue(const char *varName, float value)
Expands value to a string and calls Cvar_Set.
Definition: cvar.cpp:671
static bool cameraRoute
Definition: cl_camera.cpp:34
vec3_t speed
Definition: cl_camera.h:33
#define VectorSubtract(a, b, dest)
Definition: vector.h:45
cvar_t * cl_camzoommin
Definition: cl_camera.cpp:68
vec3_t axis[3]
Definition: cl_camera.h:36
float lerplevel
Definition: cl_camera.h:38
static cvar_t * cl_cammoveaccel
Definition: cl_camera.cpp:62
#define LEVEL_MIN
Definition: cl_camera.cpp:55