naev 0.11.5
camera.c
Go to the documentation of this file.
1/*
2 * See Licensing and Copyright notice in naev.h
3 */
11#include "naev.h"
14#include "camera.h"
15
16#include "background.h"
17#include "conf.h"
18#include "gui.h"
19#include "log.h"
20#include "nebula.h"
21#include "pause.h"
22#include "player.h"
23#include "space.h"
24
25#define CAMERA_DIR (M_PI/2.)
26
27static unsigned int camera_followpilot = 0;
28static int zoom_override = 0;
29/* Current camera position. */
30static double camera_Z = 1.;
31static double camera_X = 0.;
32static double camera_Y = 0.;
33static double camera_DX = 0.;
34static double camera_DY = 0.;
35static double camera_VX = 0.;
36static double camera_VY = 0.;
37/* Old is used to compensate pilot movement. */
38static double old_X = 0.;
39static double old_Y = 0.;
40/* Target is used why flying over with a target set. */
41static double target_Z = 0.;
42static double target_X = 0.;
43static double target_Y = 0.;
44static int camera_fly = 0;
45static double camera_flyspeed = 0.;
46static double camera_zoomspeed = 0.;
48/*
49 * Prototypes.
50 */
51static void cam_updateFly( double x, double y, double dt );
52static void cam_updatePilot( Pilot *follow, double dt );
53static void cam_updatePilotZoom( const Pilot *follow, const Pilot *target, double dt );
54static void cam_updateManualZoom( double dt );
55
61void cam_zoomOverride( int enable )
62{
63 zoom_override = enable;
64}
65
73void cam_setZoom( double zoom )
74{
75 camera_Z = CLAMP( conf.zoom_far, conf.zoom_near, zoom );
76}
77
86void cam_setZoomTarget( double zoom, double speed )
87{
88 target_Z = CLAMP( conf.zoom_far, conf.zoom_near, zoom );
89 camera_zoomspeed = speed;
90}
91
97double cam_getZoom (void)
98{
99 return camera_Z;
100}
101
107double cam_getZoomTarget (void)
108{
109 return target_Z;
110}
111
118void cam_getPos( double *x, double *y )
119{
120 *x = camera_X;
121 *y = camera_Y;
122}
123
127void cam_getDPos( double *dx, double *dy )
128{
129 *dx = camera_DX;
130 *dy = camera_DY;
131}
132
136void cam_getVel( double *vx, double *vy )
137{
138 *vx = camera_VX;
139 *vy = camera_VY;
140}
141
145void cam_setTargetPilot( unsigned int follow, int soft_over )
146{
147 double dir;
148
149 /* Set the target. */
150 camera_followpilot = follow;
151 dir = CAMERA_DIR;
152
153 /* Set camera if necessary. */
154 if (!soft_over) {
155 if (follow != 0) {
156 Pilot *p = pilot_get( follow );
157 if (p != NULL) {
158 double x, y;
159 dir = p->solid.dir;
160 x = p->solid.pos.x;
161 y = p->solid.pos.y;
162 camera_X = x;
163 camera_Y = y;
164 old_X = x;
165 old_Y = y;
166 }
167 }
168 camera_fly = 0;
169 }
170 else {
171 old_X = camera_X;
172 old_Y = camera_Y;
173 camera_fly = 1;
174 camera_flyspeed = (double) soft_over;
175 }
176 sound_updateListener( dir, camera_X, camera_Y, 0., 0. );
177}
178
182void cam_setTargetPos( double x, double y, int soft_over )
183{
184 /* Disable pilot override. */
186
187 /* Handle non soft. */
188 if (!soft_over) {
189 camera_X = x;
190 camera_Y = y;
191 old_X = x;
192 old_Y = y;
193 camera_fly = 0;
194 }
195 else {
196 target_X = x;
197 target_Y = y;
198 old_X = camera_X;
199 old_Y = camera_Y;
200 camera_fly = 1;
201 camera_flyspeed = (double) soft_over;
202 }
203 sound_updateListener( CAMERA_DIR, camera_X, camera_Y, 0., 0. );
204}
205
211int cam_getTarget( void )
212{
213 return camera_followpilot;
214}
215
221void cam_update( double dt )
222{
223 Pilot *p;
224 double ox, oy;
225
226 /* Calculate differential. */
229 ox = old_X;
230 oy = old_Y;
231
232 /* Going to position. */
233 p = NULL;
234 if (camera_fly) {
235 if (camera_followpilot != 0) {
237 if (p == NULL) {
239 camera_fly = 0;
240 }
241 else {
242 cam_updateFly( p->solid.pos.x, p->solid.pos.y, dt );
243 cam_updatePilotZoom( p, NULL, dt );
244 }
245 }
246 else
248 }
249 else {
250 /* Track pilot. */
251 if (camera_followpilot != 0) {
253 if (p == NULL)
255 else
256 cam_updatePilot( p, dt );
257 }
258 }
259
260 /* Update manual zoom. */
261 if (conf.zoom_manual || zoom_override)
263
264 /* Set the sound. */
265 if ((p==NULL) || !SOUND_PILOT_RELATIVE) {
266 double dx = dt*(ox-camera_X);
267 double dy = dt*(oy-camera_Y);
268 sound_updateListener( CAMERA_DIR, camera_X, camera_Y, dx, dy );
269 }
270 else {
271 sound_updateListener( p->solid.dir,
272 p->solid.pos.x, p->solid.pos.y,
273 p->solid.vel.x, p->solid.vel.y );
274 }
275
276 /* Compute the position differential. */
279
280 /* Compute velocity. */
281 camera_VX = camera_DX / dt;
282 camera_VY = camera_DY / dt;
283}
284
288static void cam_updateFly( double x, double y, double dt )
289{
290 double k, dx,dy, max;
291
292 max = camera_flyspeed*dt;
293 k = 25.*dt;
294 dx = (x - camera_X)*k;
295 dy = (y - camera_Y)*k;
296 if (pow2(dx)+pow2(dy) > pow2(max)) {
297 double a = atan2( dy, dx );
298 double r = max;
299 dx = r*cos(a);
300 dy = r*sin(a);
301 }
302 camera_X += dx;
303 camera_Y += dy;
304 background_moveDust( -dx, -dy );
305
306 /* Stop within 100 pixels. */
307 if (FABS((pow2(camera_X)+pow2(camera_Y)) - (pow2(x)+pow2(y))) < 100*100) {
308 old_X = camera_X;
309 old_Y = camera_Y;
310 camera_fly = 0;
311 }
312}
313
317static void cam_updatePilot( Pilot *follow, double dt )
318{
319 Pilot *target;
320 double dir, k;
321 double x,y, dx,dy, mx,my, targ_x,targ_y, bias_x,bias_y, vx,vy;
322
323 /* Get target. */
324 if (!pilot_isFlag(follow, PILOT_HYPERSPACE) && (follow->target != follow->id))
325 target = pilot_getTarget( follow );
326 else
327 target = NULL;
328
329 /* Real diagonal might be a bit too harsh since it can cut out the ship,
330 * we'll just use the largest of the two. */
331 /*diag2 = pow2(SCREEN_W) + pow2(SCREEN_H);*/
332 /*diag2 = pow2( MIN(SCREEN_W, SCREEN_H) );*/
333 const double diag2 = 100*100;
334 x = follow->solid.pos.x;
335 y = follow->solid.pos.y;
336
337 /* Compensate player movement. */
338 mx = x - old_X;
339 my = y - old_Y;
340 camera_X += mx;
341 camera_Y += my;
342
343 /* Set old position. */
344 old_X = x;
345 old_Y = y;
346
347 /* No bias by default. */
348 bias_x = 0.;
349 bias_y = 0.;
350
351 /* Bias towards target. */
352 if (target != NULL) {
353 bias_x += target->solid.pos.x - x;
354 bias_y += target->solid.pos.y - y;
355 }
356
357 /* Bias towards velocity and facing. */
358 vx = follow->solid.vel.x*1.5;
359 vy = follow->solid.vel.y*1.5;
360 dir = angle_diff( atan2(vy,vx), follow->solid.dir);
361 dir = (M_PI - FABS(dir)) / M_PI; /* Normalize. */
362 vx *= dir;
363 vy *= dir;
364 bias_x += vx;
365 bias_y += vy;
366
367 /* Limit bias. */
368 if (pow2(bias_x)+pow2(bias_y) > diag2/2.) {
369 double a = atan2( bias_y, bias_x );
370 double r = sqrt(diag2)/2.;
371 bias_x = r*cos(a);
372 bias_y = r*sin(a);
373 }
374
375 /* Compose the target. */
376 targ_x = x + bias_x;
377 targ_y = y + bias_y;
378
379 /* Head towards target. */
380 k = 0.5*dt/dt_mod;
381 dx = (targ_x-camera_X)*k;
382 dy = (targ_y-camera_Y)*k;
383 background_moveDust( -(mx+dx), -(my+dy) );
384
385 /* Update camera. */
386 camera_X += dx;
387 camera_Y += dy;
388
389 /* Update zoom. */
390 cam_updatePilotZoom( follow, target, dt );
391}
392
396static void cam_updateManualZoom( double dt )
397{
398 double d;
399
400 if (player.p == NULL)
401 return;
402
403 /* Gradually zoom in/out. */
405 d *= dt / dt_mod; /* Remove dt dependence. */
406 if (d < 0.)
407 d *= 2.;
408 camera_Z = CLAMP( conf.zoom_far, conf.zoom_near, camera_Z + d );
409}
410
414static void cam_updatePilotZoom( const Pilot *follow, const Pilot *target, double dt )
415{
416 double d, x,y, z,tz, dx, dy;
417 double zfar, znear;
418 double c;
419
420 /* Must have auto zoom enabled. */
421 if (conf.zoom_manual || zoom_override)
422 return;
423
424 /* Minimum depends on velocity normally.
425 *
426 * w*h = A, cte area constant
427 * w/h = K, cte proportion constant
428 * d^2 = A, cte geometric longitud
429 *
430 * A_v = A*(1+v/d) area of view is based on speed
431 * A_v / A = (1 + v/d)
432 *
433 * z = A / A_v = 1. / (1 + v/d)
434 */
435 d = sqrt(SCREEN_W*SCREEN_H);
436 znear = MIN( conf.zoom_near, 1. / (0.8 + VMOD(follow->solid.vel)/d) );
437
438 /* Maximum is limited by nebulae. */
439 if (cur_system->nebu_density > 0.) {
440 c = MIN( SCREEN_W, SCREEN_H ) / 2;
441 zfar = CLAMP( conf.zoom_far, conf.zoom_near, c / nebu_getSightRadius() );
442 }
443 else
444 zfar = conf.zoom_far;
445 znear = MAX( znear, zfar );
446
447 /*
448 * Set Zoom to pilot target.
449 */
450 z = cam_getZoom();
451 if (pilot_isFlag( follow, PILOT_STEALTH )) {
452 tz = zfar;
453 }
454 else {
455 if (target != NULL) {
456 /* Get current relative target position. */
457 gui_getOffset( &x, &y );
458 x += target->solid.pos.x - follow->solid.pos.x;
459 y += target->solid.pos.y - follow->solid.pos.y;
460
461 /* Get distance ratio. */
462 dx = (SCREEN_W/2.) / (FABS(x) + 2.*target->ship->gfx_space->sw);
463 dy = (SCREEN_H/2.) / (FABS(y) + 2.*target->ship->gfx_space->sh);
464
465 /* Get zoom. */
466 tz = MIN( dx, dy );
467 }
468 else
469 tz = znear; /* Aim at in. */
470 }
471
472 /* Gradually zoom in/out. */
473 d = CLAMP(-conf.zoom_speed, conf.zoom_speed, tz - z);
474 d *= dt / dt_mod; /* Remove dt dependence. */
475 if (d < 0.)
476 d *= 2.;
477 camera_Z = CLAMP( zfar, znear, z + d);
478}
void background_moveDust(double x, double y)
Displaces the dust, useful with camera.
Definition background.c:134
void cam_getDPos(double *dx, double *dy)
Gets the camera position differential (change in last frame).
Definition camera.c:127
void cam_setZoom(double zoom)
Sets the camera zoom.
Definition camera.c:73
void cam_zoomOverride(int enable)
Overrides the zoom system.
Definition camera.c:61
static double camera_DX
Definition camera.c:33
static double target_Y
Definition camera.c:43
static double target_Z
Definition camera.c:41
static double camera_DY
Definition camera.c:34
static double camera_Z
Definition camera.c:30
void cam_setTargetPilot(unsigned int follow, int soft_over)
Sets the target to follow.
Definition camera.c:145
static int zoom_override
Definition camera.c:28
void cam_getVel(double *vx, double *vy)
Gets the camera velocity.
Definition camera.c:136
void cam_setTargetPos(double x, double y, int soft_over)
Sets the camera target to a position.
Definition camera.c:182
static void cam_updatePilot(Pilot *follow, double dt)
Updates a camera following a pilot.
Definition camera.c:317
void cam_getPos(double *x, double *y)
Gets the camera position.
Definition camera.c:118
double cam_getZoomTarget(void)
Gets the camera zoom.
Definition camera.c:107
double cam_getZoom(void)
Gets the camera zoom.
Definition camera.c:97
static double old_X
Definition camera.c:38
static int camera_fly
Definition camera.c:44
static double camera_flyspeed
Definition camera.c:45
static unsigned int camera_followpilot
Definition camera.c:27
static double target_X
Definition camera.c:42
static double old_Y
Definition camera.c:39
static void cam_updateFly(double x, double y, double dt)
Updates the camera flying to a position.
Definition camera.c:288
void cam_setZoomTarget(double zoom, double speed)
Sets the camera zoom target.
Definition camera.c:86
static double camera_Y
Definition camera.c:32
static double camera_zoomspeed
Definition camera.c:46
static double camera_X
Definition camera.c:31
void cam_update(double dt)
Updates the camera.
Definition camera.c:221
static void cam_updatePilotZoom(const Pilot *follow, const Pilot *target, double dt)
Updates the camera zoom.
Definition camera.c:414
int cam_getTarget(void)
Returns the camera's current target.
Definition camera.c:211
static void cam_updateManualZoom(double dt)
Updates the manual zoom target.
Definition camera.c:396
void gui_getOffset(double *x, double *y)
Gets the GUI offset.
Definition gui.c:2062
Header file with generic functions and naev-specifics.
#define MIN(x, y)
Definition naev.h:40
#define CLAMP(a, b, x)
Definition naev.h:41
#define pow2(x)
Definition naev.h:46
#define FABS(x)
Definition naev.h:37
#define MAX(x, y)
Definition naev.h:39
double nebu_getSightRadius(void)
Gets the nebula view radius.
Definition nebula.c:126
double dt_mod
Definition pause.c:23
Pilot * pilot_getTarget(Pilot *p)
Gets the target of a pilot using a fancy caching system.
Definition pilot.c:634
Pilot * pilot_get(unsigned int id)
Pulls a pilot out of the pilot_stack based on ID.
Definition pilot.c:620
Player_t player
Definition player.c:74
static const double c[]
Definition rng.c:264
static const double d[]
Definition rng.c:273
int sound_updateListener(double dir, double px, double py, double vx, double vy)
Updates the sound listener.
Definition sound.c:1109
StarSystem * cur_system
Definition space.c:106
The representation of an in-game pilot.
Definition pilot.h:217
unsigned int id
Definition pilot.h:218
const Ship * ship
Definition pilot.h:226
Solid solid
Definition pilot.h:227
unsigned int target
Definition pilot.h:342
double zoom_speed
Definition conf.h:136
double zoom_far
Definition conf.h:134
int zoom_manual
Definition conf.h:133
double zoom_near
Definition conf.h:135
Pilot * p
Definition player.h:101
glTexture * gfx_space
Definition ship.h:138
vec2 vel
Definition physics.h:48
double dir
Definition physics.h:46
vec2 pos
Definition physics.h:49
double sw
Definition opengl_tex.h:46
double sh
Definition opengl_tex.h:47
double y
Definition vec2.h:34
double x
Definition vec2.h:33