naev 0.12.6
camera.c
Go to the documentation of this file.
1/*
2 * See Licensing and Copyright notice in naev.h
3 */
9
11#include "naev.h"
13
14#include "camera.h"
15
16#include "background.h"
17#include "conf.h"
18#include "gui.h"
19#include "nebula.h"
20#include "ntracing.h"
21#include "pause.h"
22#include "player.h"
23#include "sound.h"
24#include "space.h"
25
26#define CAMERA_DIR ( M_PI / 2. )
27
28static unsigned int camera_followpilot = 0;
29static int zoom_override = 0;
30/* Current camera position. */
31static double camera_Z = 1.;
32static double camera_X = 0.;
33static double camera_Y = 0.;
34static double camera_DX =
35 0.;
36static double camera_DY =
37 0.;
38static double camera_VX = 0.;
39static double camera_VY = 0.;
40/* Old is used to compensate pilot movement. */
41static double old_X = 0.;
42static double old_Y = 0.;
43/* Target is used why flying over with a target set. */
44static double target_Z = 0.;
45static double target_X = 0.;
46static double target_Y = 0.;
47static int camera_fly = 0;
48static double camera_flyspeed = 0.;
49static double camera_zoomspeed = 0.;
50
51/*
52 * Prototypes.
53 */
54static void cam_updateFly( double x, double y, double dt );
55static void cam_updatePilot( Pilot *follow, double dt );
56static void cam_updatePilotZoom( const Pilot *follow, const Pilot *target,
57 double dt );
58static void cam_updateManualZoom( double dt );
59
65void cam_zoomOverride( int enable )
66{
67 zoom_override = enable;
68}
69
77void cam_setZoom( double zoom )
78{
79 camera_Z = CLAMP( conf.zoom_far, conf.zoom_near, zoom );
80}
81
90void cam_setZoomTarget( double zoom, double speed )
91{
92 target_Z = CLAMP( conf.zoom_far, conf.zoom_near, zoom );
93 camera_zoomspeed = speed;
94}
95
101double cam_getZoom( void )
102{
103 return camera_Z;
104}
105
111double cam_getZoomTarget( void )
112{
113 return target_Z;
114}
115
122void cam_getPos( double *x, double *y )
123{
124 *x = camera_X;
125 *y = camera_Y;
126}
127
131void cam_getDPos( double *dx, double *dy )
132{
133 *dx = camera_DX;
134 *dy = camera_DY;
135}
136
140void cam_getVel( double *vx, double *vy )
141{
142 *vx = camera_VX;
143 *vy = camera_VY;
144}
145
149void cam_vel( double vx, double vy )
150{
151 camera_VX = vx;
152 camera_VY = vy;
153}
154
158void cam_setTargetPilot( unsigned int follow, int soft_over )
159{
160 double dir;
161
162 /* Set the target. */
163 camera_followpilot = follow;
164 dir = CAMERA_DIR;
165
166 /* Set camera if necessary. */
167 if ( !soft_over ) {
168 if ( follow != 0 ) {
169 Pilot *p = pilot_get( follow );
170 if ( p != NULL ) {
171 double x, y;
172 dir = p->solid.dir;
173 x = p->solid.pos.x;
174 y = p->solid.pos.y;
175 camera_X = x;
176 camera_Y = y;
177 old_X = x;
178 old_Y = y;
179 }
180 }
181 camera_fly = 0;
182 } else {
183 old_X = camera_X;
184 old_Y = camera_Y;
185 camera_fly = 1;
186 camera_flyspeed = (double)soft_over;
187 }
188 sound_updateListener( dir, camera_X, camera_Y, 0., 0. );
189}
190
194void cam_setTargetPos( double x, double y, int soft_over )
195{
196 /* Disable pilot override. */
198
199 /* Handle non soft. */
200 if ( !soft_over ) {
201 camera_X = x;
202 camera_Y = y;
203 old_X = x;
204 old_Y = y;
205 camera_fly = 0;
206 } else {
207 target_X = x;
208 target_Y = y;
209 old_X = camera_X;
210 old_Y = camera_Y;
211 camera_fly = 1;
212 camera_flyspeed = (double)soft_over;
213 }
214 sound_updateListener( CAMERA_DIR, camera_X, camera_Y, 0., 0. );
215}
216
222int cam_getTarget( void )
223{
224 return camera_followpilot;
225}
226
232void cam_update( double dt )
233{
234 NTracingZone( _ctx, 1 );
235 Pilot *p;
236 double ox, oy;
237
238 /* Calculate differential. */
241 ox = old_X;
242 oy = old_Y;
243
244 /* Going to position. */
245 p = NULL;
246 if ( camera_fly ) {
247 if ( camera_followpilot != 0 ) {
249 if ( p == NULL ) {
251 camera_fly = 0;
252 } else {
253 cam_updateFly( p->solid.pos.x, p->solid.pos.y, dt );
254 cam_updatePilotZoom( p, NULL, dt );
255 }
256 } else
258 } else {
259 /* Track pilot. */
260 if ( camera_followpilot != 0 ) {
262 if ( p == NULL )
264 else
265 cam_updatePilot( p, dt );
266 }
267 }
268
269 /* Update manual zoom. */
270 if ( conf.zoom_manual || zoom_override )
272
273 /* Set the sound. */
274 if ( ( p == NULL ) || !SOUND_PILOT_RELATIVE ) {
275 double dx = dt * ( ox - camera_X );
276 double dy = dt * ( oy - camera_Y );
277 sound_updateListener( CAMERA_DIR, camera_X, camera_Y, dx, dy );
278 } else {
279 sound_updateListener( p->solid.dir, p->solid.pos.x, p->solid.pos.y,
280 p->solid.vel.x, p->solid.vel.y );
281 }
282
283 /* Compute the position differential. */
286
287 /* Compute velocity. */
288 if ( dt > DOUBLE_TOL ) {
289 camera_VX = camera_DX / dt;
290 camera_VY = camera_DY / dt;
291 }
292
293 NTracingZoneEnd( _ctx );
294}
295
299static void cam_updateFly( double x, double y, double dt )
300{
301 double k, dx, dy, max;
302
303 max = camera_flyspeed * dt;
304 k = 25. * dt;
305 dx = ( x - camera_X ) * k;
306 dy = ( y - camera_Y ) * k;
307 if ( pow2( dx ) + pow2( dy ) > pow2( max ) ) {
308 double a = atan2( dy, dx );
309 double r = max;
310 dx = r * cos( a );
311 dy = r * sin( a );
312 }
313 camera_X += dx;
314 camera_Y += dy;
315 background_moveDust( -dx, -dy );
316
317 /* Stop within 100 pixels. */
318 if ( FABS( ( pow2( camera_X ) + pow2( camera_Y ) ) -
319 ( pow2( x ) + pow2( y ) ) ) < 100 * 100 ) {
320 old_X = camera_X;
321 old_Y = camera_Y;
322 camera_fly = 0;
323 }
324}
325
329static void cam_updatePilot( Pilot *follow, double dt )
330{
331 Pilot *target;
332 double dir, k;
333 double x, y, dx, dy, mx, my, targ_x, targ_y, bias_x, bias_y, vx, vy;
334
335 /* Get target. */
336 if ( !pilot_isFlag( follow, PILOT_HYPERSPACE ) &&
337 ( follow->target != follow->id ) )
338 target = pilot_getTarget( follow );
339 else
340 target = NULL;
341
342 /* Real diagonal might be a bit too harsh since it can cut out the ship,
343 * we'll just use the largest of the two. */
344 /*diag2 = pow2(SCREEN_W) + pow2(SCREEN_H);*/
345 /*diag2 = pow2( MIN(SCREEN_W, SCREEN_H) );*/
346 const double diag2 = 100 * 100;
347 x = follow->solid.pos.x;
348 y = follow->solid.pos.y;
349
350 /* Compensate player movement. */
351 mx = x - old_X;
352 my = y - old_Y;
353 camera_X += mx;
354 camera_Y += my;
355
356 /* Set old position. */
357 old_X = x;
358 old_Y = y;
359
360 /* No bias by default. */
361 bias_x = 0.;
362 bias_y = 0.;
363
364 /* Bias towards target. */
365 if ( target != NULL ) {
366 bias_x += target->solid.pos.x - x;
367 bias_y += target->solid.pos.y - y;
368 }
369
370 /* Bias towards velocity and facing. */
371 vx = follow->solid.vel.x * 1.5;
372 vy = follow->solid.vel.y * 1.5;
373 dir = angle_diff( atan2( vy, vx ), follow->solid.dir );
374 dir = ( M_PI - FABS( dir ) ) / M_PI; /* Normalize. */
375 vx *= dir;
376 vy *= dir;
377 bias_x += vx;
378 bias_y += vy;
379
380 /* Limit bias. */
381 if ( pow2( bias_x ) + pow2( bias_y ) > diag2 / 2. ) {
382 double a = atan2( bias_y, bias_x );
383 double r = sqrt( diag2 ) / 2.;
384 bias_x = r * cos( a );
385 bias_y = r * sin( a );
386 }
387
388 /* Compose the target. */
389 targ_x = x + bias_x;
390 targ_y = y + bias_y;
391
392 /* Head towards target. */
393 k = 0.5 * dt / dt_mod;
394 dx = ( targ_x - camera_X ) * k;
395 dy = ( targ_y - camera_Y ) * k;
396 background_moveDust( -( mx + dx ), -( my + dy ) );
397
398 /* Update camera. */
399 camera_X += dx;
400 camera_Y += dy;
401
402 /* Update zoom. */
403 cam_updatePilotZoom( follow, target, dt );
404}
405
409static void cam_updateManualZoom( double dt )
410{
411 double d;
412
413 if ( player.p == NULL )
414 return;
415
416 /* Gradually zoom in/out. */
418 d *= dt / dt_mod; /* Remove dt dependence. */
419 if ( d < 0. )
420 d *= 2.;
421 camera_Z = CLAMP( conf.zoom_far, conf.zoom_near, camera_Z + d );
422}
423
427static void cam_updatePilotZoom( const Pilot *follow, const Pilot *target,
428 double dt )
429{
430 double d, x, y, z, tz, dx, dy;
431 double zfar, znear;
432 double c;
433
434 /* Must have auto zoom enabled. */
435 if ( conf.zoom_manual || zoom_override )
436 return;
437
438 /* Minimum depends on velocity normally.
439 *
440 * w*h = A, cte area constant
441 * w/h = K, cte proportion constant
442 * d^2 = A, cte geometric longitud
443 *
444 * A_v = A*(1+v/d) area of view is based on speed
445 * A_v / A = (1 + v/d)
446 *
447 * z = A / A_v = 1. / (1 + v/d)
448 */
449 d = sqrt( SCREEN_W * SCREEN_H );
450 znear = MIN( conf.zoom_near, 1. / ( 0.8 + VMOD( follow->solid.vel ) / d ) );
451
452 /* Maximum is limited by nebulae. */
453 if ( cur_system->nebu_density > 0. ) {
454 c = MIN( SCREEN_W, SCREEN_H ) / 2;
455 zfar = CLAMP( conf.zoom_far, conf.zoom_near, c / nebu_getSightRadius() );
456 } else
457 zfar = conf.zoom_far;
458 znear = MAX( znear, zfar );
459
460 /*
461 * Set Zoom to pilot target.
462 */
463 z = cam_getZoom();
464 if ( pilot_isFlag( follow, PILOT_STEALTH ) ) {
465 tz = zfar;
466 } else {
467 if ( target != NULL ) {
468 /* Get current relative target position. */
469 gui_getOffset( &x, &y );
470 x += target->solid.pos.x - follow->solid.pos.x;
471 y += target->solid.pos.y - follow->solid.pos.y;
472
473 /* Get distance ratio. */
474 dx = ( SCREEN_W / 2. ) / ( FABS( x ) + 2. * target->ship->size );
475 dy = ( SCREEN_H / 2. ) / ( FABS( y ) + 2. * target->ship->size );
476
477 /* Get zoom. */
478 tz = MIN( dx, dy );
479 } else
480 tz = znear; /* Aim at in. */
481 }
482
483 /* Gradually zoom in/out. */
484 d = CLAMP( -conf.zoom_speed, conf.zoom_speed, tz - z );
485 d *= dt / dt_mod; /* Remove dt dependence. */
486 if ( d < 0. )
487 d *= 2.;
488 camera_Z = CLAMP( zfar, znear, z + d );
489}
void background_moveDust(double x, double y)
Displaces the dust, useful with camera.
Definition background.c:145
void cam_getDPos(double *dx, double *dy)
Gets the camera position differential (change in last frame).
Definition camera.c:131
void cam_setZoom(double zoom)
Sets the camera zoom.
Definition camera.c:77
void cam_zoomOverride(int enable)
Overrides the zoom system.
Definition camera.c:65
static double camera_DX
Definition camera.c:34
static double target_Y
Definition camera.c:46
static double target_Z
Definition camera.c:44
static double camera_DY
Definition camera.c:36
static double camera_Z
Definition camera.c:31
void cam_setTargetPilot(unsigned int follow, int soft_over)
Sets the target to follow.
Definition camera.c:158
static int zoom_override
Definition camera.c:29
void cam_getVel(double *vx, double *vy)
Gets the camera velocity.
Definition camera.c:140
void cam_setTargetPos(double x, double y, int soft_over)
Sets the camera target to a position.
Definition camera.c:194
static void cam_updatePilot(Pilot *follow, double dt)
Updates a camera following a pilot.
Definition camera.c:329
void cam_getPos(double *x, double *y)
Gets the camera position.
Definition camera.c:122
double cam_getZoomTarget(void)
Gets the camera zoom.
Definition camera.c:111
double cam_getZoom(void)
Gets the camera zoom.
Definition camera.c:101
static double old_X
Definition camera.c:41
static int camera_fly
Definition camera.c:47
static double camera_flyspeed
Definition camera.c:48
static unsigned int camera_followpilot
Definition camera.c:28
static double target_X
Definition camera.c:45
static double old_Y
Definition camera.c:42
static void cam_updateFly(double x, double y, double dt)
Updates the camera flying to a position.
Definition camera.c:299
void cam_setZoomTarget(double zoom, double speed)
Sets the camera zoom target.
Definition camera.c:90
static double camera_Y
Definition camera.c:33
static double camera_zoomspeed
Definition camera.c:49
static double camera_X
Definition camera.c:32
void cam_vel(double vx, double vy)
Sets the camera velocity.
Definition camera.c:149
void cam_update(double dt)
Updates the camera.
Definition camera.c:232
static void cam_updatePilotZoom(const Pilot *follow, const Pilot *target, double dt)
Updates the camera zoom.
Definition camera.c:427
int cam_getTarget(void)
Returns the camera's current target.
Definition camera.c:222
static void cam_updateManualZoom(double dt)
Updates the manual zoom target.
Definition camera.c:409
void gui_getOffset(double *x, double *y)
Gets the GUI offset.
Definition gui.c:2159
Header file with generic functions and naev-specifics.
#define MIN(x, y)
Definition naev.h:39
#define CLAMP(a, b, x)
Definition naev.h:41
#define pow2(x)
Definition naev.h:53
#define FABS(x)
Definition naev.h:34
#define MAX(x, y)
Definition naev.h:37
double nebu_getSightRadius(void)
Gets the nebula view radius.
Definition nebula.c:124
double dt_mod
Definition pause.c:20
Pilot * pilot_getTarget(Pilot *p)
Gets the target of a pilot using a fancy caching system.
Definition pilot.c:655
Pilot * pilot_get(unsigned int id)
Pulls a pilot out of the pilot_stack based on ID.
Definition pilot.c:640
Player_t player
Definition player.c:77
static const double c[]
Definition rng.c:256
static const double d[]
Definition rng.c:263
int sound_updateListener(double dir, double px, double py, double vx, double vy)
Updates the sound listener.
Definition sound.c:1115
StarSystem * cur_system
Definition space.c:110
The representation of an in-game pilot.
Definition pilot.h:263
unsigned int id
Definition pilot.h:264
const Ship * ship
Definition pilot.h:274
Solid solid
Definition pilot.h:275
unsigned int target
Definition pilot.h:400
double size
Definition ship.h:149
vec2 vel
Definition physics.h:48
double dir
Definition physics.h:46
vec2 pos
Definition physics.h:49
double y
Definition vec2.h:47
double x
Definition vec2.h:46