1 //********************************************************************************************
2 //*
3 //* This file is part of Egoboo.
4 //*
5 //* Egoboo is free software: you can redistribute it and/or modify it
6 //* under the terms of the GNU General Public License as published by
7 //* the Free Software Foundation, either version 3 of the License, or
8 //* (at your option) any later version.
9 //*
10 //* Egoboo is distributed in the hope that it will be useful, but
11 //* WITHOUT ANY WARRANTY; without even the implied warranty of
12 //* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 //* General Public License for more details.
14 //*
15 //* You should have received a copy of the GNU General Public License
16 //* along with Egoboo. If not, see <http://www.gnu.org/licenses/>.
17 //*
18 //********************************************************************************************
19
20 /// @file camera.c
21 /// @brief Various functions related to how the game camera works.
22 /// @details
23
24 #include "camera.h"
25
26 #include "char.inl"
27 #include "mesh.inl"
28
29 #include "input.h"
30 #include "graphic.h"
31 #include "network.h"
32 #include "controls_file.h"
33
34 #include "egoboo_setup.h"
35 #include "egoboo.h"
36
37 #include "SDL_extensions.h"
38
39 //--------------------------------------------------------------------------------------------
40 //--------------------------------------------------------------------------------------------
41
42 camera_t gCamera;
43
44 //--------------------------------------------------------------------------------------------
45 //--------------------------------------------------------------------------------------------
46 // Camera control stuff
47
48 //--------------------------------------------------------------------------------------------
camera_rotmesh__init()49 void camera_rotmesh__init()
50 {
51 // Matrix init stuff (from remove.c)
52 rotmesh_topside = (( float )sdl_scr.x / sdl_scr.y ) * CAM_ROTMESH_TOPSIDE / ( 1.33333f );
53 rotmesh_bottomside = (( float )sdl_scr.x / sdl_scr.y ) * CAM_ROTMESH_BOTTOMSIDE / ( 1.33333f );
54 rotmesh_up = (( float )sdl_scr.x / sdl_scr.y ) * CAM_ROTMESH_UP / ( 1.33333f );
55 rotmesh_down = (( float )sdl_scr.x / sdl_scr.y ) * CAM_ROTMESH_DOWN / ( 1.33333f );
56 }
57
58 //--------------------------------------------------------------------------------------------
camera_ctor(camera_t * pcam)59 camera_t * camera_ctor( camera_t * pcam )
60 {
61 /// @detalis BB@> initialize the camera structure
62
63 fvec3_t t1 = {{0, 0, 0}};
64 fvec3_t t2 = {{0, 0, -1}};
65 fvec3_t t3 = {{0, 1, 0}};
66
67 memset( pcam, 0, sizeof( *pcam ) );
68
69 pcam->move_mode = pcam->move_mode_old = CAM_PLAYER;
70 pcam->turn_mode = cfg.autoturncamera;
71
72 pcam->swing = 0;
73 pcam->swingrate = 0;
74 pcam->swingamp = 0;
75 pcam->pos.x = 0;
76 pcam->pos.y = 1500;
77 pcam->pos.z = 1500;
78 pcam->zoom = 1000;
79 pcam->zadd = 800;
80 pcam->zaddgoto = 800;
81 pcam->zgoto = 800;
82 pcam->turn_z_rad = -PI / 4.0f;
83 pcam->turn_z_one = pcam->turn_z_rad / TWO_PI;
84 pcam->ori.facing_z = CLIP_TO_16BITS(( int )( pcam->turn_z_one * ( float )0x00010000 ) ) ;
85 pcam->turnadd = 0;
86 pcam->sustain = 0.60f;
87 pcam->turnupdown = ( float )( PI / 4 );
88 pcam->roll = 0;
89 pcam->motion_blur = 0;
90
91 pcam->mView = pcam->mViewSave = ViewMatrix( t1.v, t2.v, t3.v, 0 );
92 pcam->mProjection = ProjectionMatrix( .001f, 2000.0f, ( float )( CAM_FOV * PI / 180 ) ); // 60 degree CAM_FOV
93 pcam->mProjection = MatrixMult( Translate( 0, 0, -0.999996f ), pcam->mProjection ); // Fix Z value...
94 pcam->mProjection = MatrixMult( ScaleXYZ( -1, -1, 100000 ), pcam->mProjection ); // HUK // ...'cause it needs it
95
96 // [claforte] Fudge the values.
97 pcam->mProjection.v[10] /= 2.0f;
98 pcam->mProjection.v[11] /= 2.0f;
99
100 camera_rotmesh__init();
101
102 return pcam;
103 }
104
105 //--------------------------------------------------------------------------------------------
106 //--------------------------------------------------------------------------------------------
dump_matrix(fmat_4x4_t a)107 void dump_matrix( fmat_4x4_t a )
108 {
109 /// @detalis ZZ@> dump a text representation of a 4x4 matrix to stdout
110
111 int i; int j;
112
113 for ( j = 0; j < 4; j++ )
114 {
115 printf( " " );
116
117 for ( i = 0; i < 4; i++ )
118 {
119 printf( "%f ", a.CNV( i, j ) );
120 }
121 printf( "\n" );
122 }
123 }
124
125 //--------------------------------------------------------------------------------------------
126 //--------------------------------------------------------------------------------------------
camera_look_at(camera_t * pcam,float x,float y)127 void camera_look_at( camera_t * pcam, float x, float y )
128 {
129 /// @details ZZ@> This function makes the camera turn to face the character
130
131 pcam->zgoto = pcam->zadd;
132 if ( 0 != pcam->turn_time )
133 {
134 pcam->turn_z_rad = ( 1.5f * PI ) - ATAN2( y - pcam->pos.y, x - pcam->pos.x ); // xgg
135 }
136 }
137
138 //--------------------------------------------------------------------------------------------
camera_make_matrix(camera_t * pcam)139 void camera_make_matrix( camera_t * pcam )
140 {
141 /// @details ZZ@> This function sets pcam->mView to the camera's location and rotation
142
143 float local_swingamp = pcam->swingamp;
144
145 //Fade out the motion blur
146 if ( pcam->motion_blur > 0 )
147 {
148 pcam->motion_blur *= 0.99f; //Decay factor
149 if ( pcam->motion_blur < 0.001f ) pcam->motion_blur = 0;
150 }
151
152 //Swing the camera if players are groggy and apply motion blur
153 if ( local_stats.grog_level > 0 )
154 {
155 float zoom_add;
156 pcam->swing = ( pcam->swing + 120 ) & 0x3FFF;
157 local_swingamp = MAX( local_swingamp, 0.175f );
158
159 zoom_add = ( 0 == ((( int )local_stats.grog_level ) % 2 ) ? 1 : - 1 ) * CAM_TURN_KEY * local_stats.grog_level * 0.35f;
160 pcam->zaddgoto = CLIP( pcam->zaddgoto + zoom_add, CAM_ZADD_MIN, CAM_ZADD_MAX );
161 pcam->motion_blur = MIN( 1.00f, 0.5f + 0.03f * local_stats.grog_level );
162 }
163
164 //Rotate camera if they are dazed and apply motion blur
165 if ( local_stats.daze_level > 0 )
166 {
167 pcam->turnadd = local_stats.daze_level * CAM_TURN_KEY * 0.5f;
168 pcam->motion_blur = MIN( 1.00f, 0.5f + 0.03f * local_stats.daze_level );
169 }
170
171 //Apply camera swinging
172 pcam->mView = MatrixMult( Translate( pcam->pos.x, -pcam->pos.y, pcam->pos.z ), pcam->mViewSave ); // xgg
173 if ( local_swingamp > 0.001f )
174 {
175 pcam->roll = turntosin[pcam->swing] * local_swingamp;
176 pcam->mView = MatrixMult( RotateY( pcam->roll ), pcam->mView );
177 }
178
179 // If the camera stops swinging for some reason, slowly return to original position
180 else if ( 0 != pcam->roll )
181 {
182 pcam->roll *= 0.9875f; //Decay factor
183 pcam->mView = MatrixMult( RotateY( pcam->roll ), pcam->mView );
184
185 // Come to a standstill at some point
186 if ( ABS( pcam->roll ) < 0.001f )
187 {
188 pcam->roll = 0;
189 pcam->swing = 0;
190 }
191 }
192
193 pcam->mView = MatrixMult( RotateZ( pcam->turn_z_rad ), pcam->mView );
194 pcam->mView = MatrixMult( RotateX( pcam->turnupdown ), pcam->mView );
195
196 //--- pre-compute some camera vectors
197 mat_getCamForward( pcam->mView.v, pcam->vfw.v );
198 fvec3_self_normalize( pcam->vfw.v );
199
200 mat_getCamUp( pcam->mView.v, pcam->vup.v );
201 fvec3_self_normalize( pcam->vup.v );
202
203 mat_getCamRight( pcam->mView.v, pcam->vrt.v );
204 fvec3_self_normalize( pcam->vrt.v );
205 }
206
207 //--------------------------------------------------------------------------------------------
camera_adjust_angle(camera_t * pcam,float height)208 void camera_adjust_angle( camera_t * pcam, float height )
209 {
210 /// @details ZZ@> This function makes the camera look downwards as it is raised up
211
212 float percentmin, percentmax;
213 if ( height < CAM_ZADD_MIN ) height = CAM_ZADD_MIN;
214
215 percentmax = ( height - CAM_ZADD_MIN ) / ( float )( CAM_ZADD_MAX - CAM_ZADD_MIN );
216 percentmin = 1.0f - percentmax;
217
218 pcam->turnupdown = (( CAM_UPDOWN_MIN * percentmin ) + ( CAM_UPDOWN_MAX * percentmax ) );
219 pcam->zoom = ( CAM_ZOOM_MIN * percentmin ) + ( CAM_ZOOM_MAX * percentmax );
220 }
221
222 //--------------------------------------------------------------------------------------------
camera_move(camera_t * pcam,ego_mpd_t * pmesh)223 void camera_move( camera_t * pcam, ego_mpd_t * pmesh )
224 {
225 /// @details ZZ@> This function moves the camera
226
227 Uint16 cnt;
228 float x, y, z, level, newx, newy, movex, movey;
229 Uint16 turnsin;
230
231 if ( CAM_TURN_NONE != pcam->turn_mode )
232 pcam->turn_time = 255;
233 else if ( 0 != pcam->turn_time )
234 pcam->turn_time--;
235
236 // the default camera motion is to do nothing
237 x = pcam->track_pos.x;
238 y = pcam->track_pos.y;
239 z = pcam->track_pos.z;
240 level = 128 + mesh_get_level( pmesh, x, y );
241
242 if ( CAM_FREE == pcam->move_mode )
243 {
244 // the keypad controls the camera
245 if ( SDLKEYDOWN( SDLK_KP8 ) )
246 {
247 pcam->track_pos.x -= pcam->mView.CNV( 0, 1 ) * 50;
248 pcam->track_pos.y -= pcam->mView.CNV( 1, 1 ) * 50;
249 }
250
251 if ( SDLKEYDOWN( SDLK_KP2 ) )
252 {
253 pcam->track_pos.x += pcam->mView.CNV( 0, 1 ) * 50;
254 pcam->track_pos.y += pcam->mView.CNV( 1, 1 ) * 50;
255 }
256
257 if ( SDLKEYDOWN( SDLK_KP4 ) )
258 {
259 pcam->track_pos.x += pcam->mView.CNV( 0, 0 ) * 50;
260 pcam->track_pos.y += pcam->mView.CNV( 1, 0 ) * 50;
261 }
262
263 if ( SDLKEYDOWN( SDLK_KP6 ) )
264 {
265 pcam->track_pos.x -= pcam->mView.CNV( 0, 0 ) * 10;
266 pcam->track_pos.y -= pcam->mView.CNV( 1, 0 ) * 10;
267 }
268
269 if ( SDLKEYDOWN( SDLK_KP7 ) )
270 {
271 pcam->turnadd += CAM_TURN_KEY;
272 }
273
274 if ( SDLKEYDOWN( SDLK_KP9 ) )
275 {
276 pcam->turnadd -= CAM_TURN_KEY;
277 }
278
279 pcam->track_pos.z = 128 + mesh_get_level( pmesh, pcam->track_pos.x, pcam->track_pos.y );
280 }
281 else if ( CAM_RESET == pcam->move_mode )
282 {
283 // a camera movement mode for re-focusing in on a bunch of players
284
285 PLA_REF ipla;
286 fvec3_t sum_pos;
287 float sum_wt, sum_level;
288
289 sum_wt = 0.0f;
290 sum_level = 0.0f;
291 fvec3_self_clear( sum_pos.v );
292
293 for ( ipla = 0; ipla < MAX_PLAYER; ipla++ )
294 {
295 chr_t * pchr;
296
297 pchr = pla_get_pchr( ipla );
298 if ( NULL == pchr || !pchr->alive ) continue;
299
300 sum_pos.x += pchr->pos.x;
301 sum_pos.y += pchr->pos.y;
302 sum_pos.z += pchr->pos.z + pchr->chr_min_cv.maxs[OCT_Z] * 0.9f;
303 sum_level += pchr->enviro.level;
304 sum_wt += 1.0f;
305 }
306
307 // if any of the characters is doing anything
308 if ( sum_wt > 0.0f )
309 {
310 x = sum_pos.x / sum_wt;
311 y = sum_pos.y / sum_wt;
312 z = sum_pos.z / sum_wt;
313 level = sum_level / sum_wt;
314 }
315 }
316 else if ( CAM_PLAYER == pcam->move_mode )
317 {
318 // a camera mode for focusing in on the players that are actually doing something.
319 // "Show me the drama!"
320
321 PLA_REF ipla;
322 chr_t * local_chr_ptrs[MAX_PLAYER];
323 int local_chr_count = 0;
324
325 // count the number of local players, first
326 local_chr_count = 0;
327 for ( ipla = 0; ipla < MAX_PLAYER; ipla++ )
328 {
329 chr_t * pchr;
330
331 pchr = pla_get_pchr( ipla );
332 if ( NULL == pchr || !pchr->alive ) continue;
333
334 local_chr_ptrs[local_chr_count] = pchr;
335 local_chr_count++;
336 }
337
338 if ( 0 == local_chr_count )
339 {
340 // do nothing
341 }
342 else if ( 1 == local_chr_count )
343 {
344 // copy from the one character
345
346 x = local_chr_ptrs[0]->pos.x;
347 y = local_chr_ptrs[0]->pos.y;
348 z = local_chr_ptrs[0]->pos.z;
349 level = local_chr_ptrs[0]->enviro.level;
350 }
351 else
352 {
353 // use the characer's "activity" to average the position the camera is viewing
354
355 fvec3_t sum_pos;
356 float sum_wt, sum_level;
357
358 sum_wt = 0.0f;
359 sum_level = 0.0f;
360 fvec3_self_clear( sum_pos.v );
361
362 for ( cnt = 0; cnt < local_chr_count; cnt++ )
363 {
364 chr_t * pchr;
365 float weight1, weight2, weight;
366
367 // we JUST checked the validity of these characters. No need to do it again?
368 pchr = local_chr_ptrs[ cnt ];
369
370 // weight it by the character's velocity^2, so that
371 // inactive characters don't control the camera
372 weight1 = fvec3_dot_product( pchr->vel.v, pchr->vel.v );
373
374 // make another weight based on button-pushing
375 weight2 = ( 0 == pchr->latch.b ) ? 0 : 127;
376
377 // I would weight this by the amount of damage that the character just sustained,
378 // but there is no real way to do this?
379
380 // get the maximum effect
381 weight = MAX( weight1, weight2 );
382
383 // The character is on foot
384 sum_pos.x += pchr->pos.x * weight;
385 sum_pos.y += pchr->pos.y * weight;
386 sum_pos.z += pchr->pos.z * weight;
387 sum_level += pchr->enviro.level * weight;
388 sum_wt += weight;
389 }
390
391 // if any of the characters is doing anything
392 if ( sum_wt > 0 )
393 {
394 x = sum_pos.x / sum_wt;
395 y = sum_pos.y / sum_wt;
396 z = sum_pos.z / sum_wt;
397 level = sum_level / sum_wt;
398 }
399 }
400 }
401
402 if ( CAM_RESET == pcam->move_mode )
403 {
404 // just set the position
405 pcam->track_pos.x = x;
406 pcam->track_pos.y = y;
407 pcam->track_pos.z = z;
408 pcam->track_level = level;
409
410 // reset the camera mode
411 pcam->move_mode = pcam->move_mode_old;
412 }
413 else
414 {
415 // smoothly interpolate the camera tracking position
416 pcam->track_pos.x = 0.9f * pcam->track_pos.x + 0.1f * x;
417 pcam->track_pos.y = 0.9f * pcam->track_pos.y + 0.1f * y;
418 pcam->track_pos.z = 0.9f * pcam->track_pos.z + 0.1f * z;
419 pcam->track_level = 0.9f * pcam->track_level + 0.1f * level;
420 }
421
422 pcam->turnadd = pcam->turnadd * pcam->sustain;
423 pcam->zadd = 0.9f * pcam->zadd + 0.1f * pcam->zaddgoto;
424 pcam->pos.z = 0.9f * pcam->pos.z + 0.1f * pcam->zgoto;
425
426 // Camera controls
427 if ( CAM_TURN_GOOD == pcam->turn_mode && 1 == local_numlpla )
428 {
429 if ( mous.on )
430 {
431 if ( !control_is_pressed( INPUT_DEVICE_MOUSE, CONTROL_CAMERA ) )
432 {
433 pcam->turnadd -= ( mous.x * 0.5f );
434 }
435 }
436
437 if ( keyb.on )
438 {
439 pcam->turnadd += ( control_is_pressed( INPUT_DEVICE_KEYBOARD, CONTROL_LEFT ) - control_is_pressed( INPUT_DEVICE_KEYBOARD, CONTROL_RIGHT ) ) * CAM_TURN_KEY;
440 }
441
442 if ( joy[0].on )
443 {
444 if ( !control_is_pressed( INPUT_DEVICE_JOY_A, CONTROL_CAMERA ) )
445 {
446 pcam->turnadd -= joy[0].x * CAM_TURN_JOY;
447 }
448 }
449
450 if ( joy[1].on )
451 {
452 if ( !control_is_pressed( INPUT_DEVICE_JOY_B, CONTROL_CAMERA ) )
453 {
454 pcam->turnadd -= joy[1].x * CAM_TURN_JOY;
455 }
456 }
457 }
458 else
459 {
460 if ( mous.on )
461 {
462 if ( control_is_pressed( INPUT_DEVICE_MOUSE, CONTROL_CAMERA ) )
463 {
464 pcam->turnadd += ( mous.x / 3.0f );
465 pcam->zaddgoto += ( float ) mous.y / 3.0f;
466 if ( pcam->zaddgoto < CAM_ZADD_MIN ) pcam->zaddgoto = CAM_ZADD_MIN;
467 if ( pcam->zaddgoto > CAM_ZADD_MAX ) pcam->zaddgoto = CAM_ZADD_MAX;
468
469 pcam->turn_time = CAM_TURN_TIME; // Sticky turn...
470 }
471 }
472
473 // JoyA camera controls
474 if ( joy[0].on )
475 {
476 if ( control_is_pressed( INPUT_DEVICE_JOY_A, CONTROL_CAMERA ) )
477 {
478 pcam->turnadd += joy[0].x * CAM_TURN_JOY;
479 pcam->zaddgoto += joy[0].y * CAM_TURN_JOY;
480 if ( pcam->zaddgoto < CAM_ZADD_MIN ) pcam->zaddgoto = CAM_ZADD_MIN;
481 if ( pcam->zaddgoto > CAM_ZADD_MAX ) pcam->zaddgoto = CAM_ZADD_MAX;
482
483 pcam->turn_time = CAM_TURN_TIME; // Sticky turn...
484 }
485 }
486
487 // JoyB camera controls
488 if ( joy[1].on )
489 {
490 if ( control_is_pressed( INPUT_DEVICE_JOY_B, CONTROL_CAMERA ) )
491 {
492 pcam->turnadd += joy[1].x * CAM_TURN_JOY;
493 pcam->zaddgoto += joy[1].y * CAM_TURN_JOY;
494 if ( pcam->zaddgoto < CAM_ZADD_MIN ) pcam->zaddgoto = CAM_ZADD_MIN;
495 if ( pcam->zaddgoto > CAM_ZADD_MAX ) pcam->zaddgoto = CAM_ZADD_MAX;
496
497 pcam->turn_time = CAM_TURN_TIME; // Sticky turn...
498 }
499 }
500 }
501
502 // Keyboard camera controls
503 if ( keyb.on )
504 {
505 if ( control_is_pressed( INPUT_DEVICE_KEYBOARD, CONTROL_CAMERA_LEFT ) || control_is_pressed( INPUT_DEVICE_KEYBOARD, CONTROL_CAMERA_RIGHT ) )
506 {
507 pcam->turnadd += ( control_is_pressed( INPUT_DEVICE_KEYBOARD, CONTROL_CAMERA_LEFT ) - control_is_pressed( INPUT_DEVICE_KEYBOARD, CONTROL_CAMERA_RIGHT ) ) * CAM_TURN_KEY;
508 pcam->turn_time = CAM_TURN_TIME; // Sticky turn...
509 }
510
511 if ( control_is_pressed( INPUT_DEVICE_KEYBOARD, CONTROL_CAMERA_IN ) || control_is_pressed( INPUT_DEVICE_KEYBOARD, CONTROL_CAMERA_OUT ) )
512 {
513 pcam->zaddgoto += ( control_is_pressed( INPUT_DEVICE_KEYBOARD, CONTROL_CAMERA_OUT ) - control_is_pressed( INPUT_DEVICE_KEYBOARD, CONTROL_CAMERA_IN ) ) * CAM_TURN_KEY;
514 if ( pcam->zaddgoto < CAM_ZADD_MIN ) pcam->zaddgoto = CAM_ZADD_MIN;
515 if ( pcam->zaddgoto > CAM_ZADD_MAX ) pcam->zaddgoto = CAM_ZADD_MAX;
516 }
517 }
518
519 pcam->pos.x -= ( float )( pcam->mView.CNV( 0, 0 ) ) * pcam->turnadd; // xgg
520 pcam->pos.y += ( float )( pcam->mView.CNV( 1, 0 ) ) * -pcam->turnadd;
521
522 // Center on target for doing rotation...
523 if ( 0 != pcam->turn_time )
524 {
525 pcam->center.x = pcam->center.x * 0.9f + pcam->track_pos.x * 0.1f;
526 pcam->center.y = pcam->center.y * 0.9f + pcam->track_pos.y * 0.1f;
527 }
528
529 // Create a tolerance area for walking without camera movement
530 x = pcam->track_pos.x - pcam->pos.x;
531 y = pcam->track_pos.y - pcam->pos.y;
532 newx = -( pcam->mView.CNV( 0, 0 ) * x + pcam->mView.CNV( 1, 0 ) * y ); // newx = -(pcam->mView(0,0) * x + pcam->mView(1,0) * y);
533 newy = -( pcam->mView.CNV( 0, 1 ) * x + pcam->mView.CNV( 1, 1 ) * y ); // newy = -(pcam->mView(0,1) * x + pcam->mView(1,1) * y);
534
535 // Get ready to scroll...
536 movex = 0;
537 movey = 0;
538
539 // Adjust for camera height...
540 z = ( CAM_TRACK_X_AREA_LOW * ( CAM_ZADD_MAX - pcam->zadd ) ) +
541 ( CAM_TRACK_X_AREA_HIGH * ( pcam->zadd - CAM_ZADD_MIN ) );
542 z = z / ( CAM_ZADD_MAX - CAM_ZADD_MIN );
543 if ( newx < -z )
544 {
545 // Scroll left
546 movex += ( newx + z );
547 }
548 if ( newx > z )
549 {
550 // Scroll right
551 movex += ( newx - z );
552 }
553
554 // Adjust for camera height...
555 z = ( CAM_TRACK_Y_AREA_MINLOW * ( CAM_ZADD_MAX - pcam->zadd ) ) +
556 ( CAM_TRACK_Y_AREA_MINHIGH * ( pcam->zadd - CAM_ZADD_MIN ) );
557 z = z / ( CAM_ZADD_MAX - CAM_ZADD_MIN );
558 if ( newy < z )
559 {
560 // Scroll down
561 movey -= ( newy - z );
562 }
563 else
564 {
565 // Adjust for camera height...
566 z = ( CAM_TRACK_Y_AREA_MAXLOW * ( CAM_ZADD_MAX - pcam->zadd ) ) +
567 ( CAM_TRACK_Y_AREA_MAXHIGH * ( pcam->zadd - CAM_ZADD_MIN ) );
568 z = z / ( CAM_ZADD_MAX - CAM_ZADD_MIN );
569 if ( newy > z )
570 {
571 // Scroll up
572 movey -= ( newy - z );
573 }
574 }
575
576 turnsin = TO_TURN( pcam->ori.facing_z );
577 pcam->center.x += movex * turntocos[ turnsin & TRIG_TABLE_MASK ] + movey * turntosin[ turnsin & TRIG_TABLE_MASK ];
578 pcam->center.y += -movex * turntosin[ turnsin & TRIG_TABLE_MASK ] + movey * turntocos[ turnsin & TRIG_TABLE_MASK ];
579
580 // Finish up the camera
581 camera_look_at( pcam, pcam->center.x, pcam->center.y );
582 pcam->pos.x = ( float ) pcam->center.x + ( pcam->zoom * SIN( pcam->turn_z_rad ) );
583 pcam->pos.y = ( float ) pcam->center.y + ( pcam->zoom * COS( pcam->turn_z_rad ) );
584
585 camera_adjust_angle( pcam, pcam->pos.z );
586
587 camera_make_matrix( pcam );
588
589 pcam->turn_z_one = ( pcam->turn_z_rad ) / ( TWO_PI );
590 pcam->ori.facing_z = CLIP_TO_16BITS( FLOAT_TO_FP16( pcam->turn_z_one ) );
591 }
592
593 //--------------------------------------------------------------------------------------------
camera_reset(camera_t * pcam,ego_mpd_t * pmesh)594 void camera_reset( camera_t * pcam, ego_mpd_t * pmesh )
595 {
596 /// @details ZZ@> This function makes sure the camera starts in a suitable position
597
598 pcam->swing = 0;
599 pcam->pos.x = pmesh->gmem.edge_x / 2;
600 pcam->pos.y = pmesh->gmem.edge_y / 2;
601 pcam->pos.z = 1500;
602 pcam->zoom = 1000;
603 pcam->center.x = pcam->pos.x;
604 pcam->center.y = pcam->pos.y;
605 pcam->track_pos.x = pcam->pos.x;
606 pcam->track_pos.y = pcam->pos.y;
607 pcam->track_pos.z = 1500;
608 pcam->turnadd = 0;
609 pcam->track_level = 0;
610 pcam->zadd = 1500;
611 pcam->zaddgoto = CAM_ZADD_MAX;
612 pcam->zgoto = 1500;
613 pcam->turn_z_rad = -PI / 4.0f;
614 pcam->turn_z_one = pcam->turn_z_rad / TWO_PI;
615 pcam->ori.facing_z = CLIP_TO_16BITS(( int )( pcam->turn_z_one * ( float )0x00010000 ) ) ;
616 pcam->turnupdown = PI / 4.0f;
617 pcam->roll = 0;
618
619 // make sure you are looking at the players
620 camera_reset_target( pcam, pmesh );
621 }
622
623 //--------------------------------------------------------------------------------------------
camera_reset_target(camera_t * pcam,ego_mpd_t * pmesh)624 bool_t camera_reset_target( camera_t * pcam, ego_mpd_t * pmesh )
625 {
626 // @details BB@> Force the camera to focus in on the players. Should be called any time there is
627 // a "change of scene". With the new velocity-tracking of the camera, this would include
628 // things like character respawns, adding new players, etc.
629
630 int turn_mode_save;
631
632 if ( NULL == pcam ) return bfalse;
633
634 turn_mode_save = pcam->turn_mode;
635
636 // set an identity matrix.
637 pcam->mView = IdentityMatrix();
638
639 // specify the modes that will make the camera point at the players
640 pcam->turn_mode = CAM_TURN_AUTO;
641 pcam->move_mode = CAM_RESET;
642
643 // If you use CAM_RESET, camera_move() automatically restores pcam->move_mode
644 // to its default setting
645 camera_move( pcam, pmesh );
646
647 // fix the center position
648 pcam->center.x = pcam->track_pos.x;
649 pcam->center.y = pcam->track_pos.y;
650
651 // restore the turn mode
652 pcam->turn_mode = turn_mode_save;
653 pcam->turn_time = 0;
654
655 return btrue;
656 }
657