revision 2
[carveJwlIkooP6JGAAIwe30JlM.git] / player_common.c
1 #include "ent_skateshop.h"
2 #include "player.h"
3 #include "input.h"
4 #include "menu.h"
5 #include "vg/vg_perlin.h"
6
7 static float player_get_heading_yaw(void){
8 v3f xz;
9 q_mulv( localplayer.rb.q, (v3f){ 0.0f,0.0f,1.0f }, xz );
10 return atan2f( xz[0], xz[2] );
11 }
12
13 static void player_camera_portal_correction(void){
14 if( localplayer.gate_waiting ){
15 /* construct plane equation for reciever gate */
16 v4f plane;
17 q_mulv( localplayer.gate_waiting->q[1], (v3f){0.0f,0.0f,1.0f}, plane );
18 plane[3] = v3_dot( plane, localplayer.gate_waiting->co[1] );
19
20 f32 pol = v3_dot( localplayer.cam.pos, plane ) - plane[3];
21
22 int cleared = (pol < 0.0f) || (pol > 5.0f);
23
24 if( cleared ){
25 vg_success( "Plane cleared\n" );
26 }
27
28 m4x3f inverse;
29 m4x3_invert_affine( localplayer.gate_waiting->transport, inverse );
30
31 /* de-transform camera and player back */
32 v3f v0;
33 m4x3_mulv( inverse, localplayer.cam.pos, localplayer.cam.pos );
34 v3_angles_vector( localplayer.cam.angles, v0 );
35 m3x3_mulv( inverse, v0, v0 );
36 v3_angles( v0, localplayer.cam.angles );
37
38 skeleton_apply_transform( &localplayer.skeleton, inverse,
39 localplayer.final_mtx );
40
41 /* record and re-put things again */
42 if( cleared )
43 {
44 skaterift_record_frame( &player_replay.local, 1 );
45 localplayer.deferred_frame_record = 1;
46
47 skeleton_apply_transform( &localplayer.skeleton,
48 localplayer.gate_waiting->transport,
49 localplayer.final_mtx );
50
51 m4x3_mulv( localplayer.gate_waiting->transport,
52 localplayer.cam.pos, localplayer.cam.pos );
53 v3_angles_vector( localplayer.cam.angles, v0 );
54 m3x3_mulv( localplayer.gate_waiting->transport, v0, v0 );
55 v3_angles( v0, localplayer.cam.angles );
56 player_apply_transport_to_cam( localplayer.gate_waiting->transport );
57 localplayer.gate_waiting = NULL;
58 }
59 }
60 }
61
62 static void player__cam_iterate(void){
63 struct player_cam_controller *cc = &localplayer.cam_control;
64
65 if( localplayer.subsystem == k_player_subsystem_walk ){
66 v3_copy( (v3f){-0.1f,1.8f,0.0f}, cc->fpv_viewpoint );
67 v3_copy( (v3f){0.0f,0.0f,0.0f}, cc->fpv_offset );
68 v3_copy( (v3f){0.0f,1.4f,0.0f}, cc->tpv_offset );
69 }
70 else if( localplayer.subsystem == k_player_subsystem_glide ){
71 v3_copy( (v3f){-0.15f,1.75f,0.0f}, cc->fpv_viewpoint );
72 v3_copy( (v3f){0.0f,0.0f,0.0f}, cc->fpv_offset );
73 v3_copy( (v3f){0.0f,-1.0f,0.0f}, cc->tpv_offset );
74 v3_add( cc->tpv_offset_extra, cc->tpv_offset, cc->tpv_offset );
75 }
76 else{
77 v3_copy( (v3f){-0.15f,1.75f,0.0f}, cc->fpv_viewpoint );
78 v3_copy( (v3f){0.0f,0.0f,0.0f}, cc->fpv_offset );
79
80 f32 h = vg_lerpf( 0.4f, 1.4f, k_cam_height );
81 v3_copy( (v3f){0.0f,h,0.0f}, cc->tpv_offset );
82 v3_add( cc->tpv_offset_extra, cc->tpv_offset, cc->tpv_offset );
83 }
84
85 localplayer.cam_velocity_constant = 0.25f;
86 localplayer.cam_velocity_coefficient = 0.7f;
87
88 /* lerping */
89
90 if( localplayer.cam_dist_smooth == 0.0f ){
91 localplayer.cam_dist_smooth = localplayer.cam_dist;
92 }
93 else {
94 localplayer.cam_dist_smooth = vg_lerpf(
95 localplayer.cam_dist_smooth,
96 localplayer.cam_dist,
97 vg.time_frame_delta * 8.0f );
98 }
99
100 localplayer.cam_velocity_influence_smooth = vg_lerpf(
101 localplayer.cam_velocity_influence_smooth,
102 localplayer.cam_velocity_influence,
103 vg.time_frame_delta * 8.0f );
104
105 localplayer.cam_velocity_coefficient_smooth = vg_lerpf(
106 localplayer.cam_velocity_coefficient_smooth,
107 localplayer.cam_velocity_coefficient,
108 vg.time_frame_delta * 8.0f );
109
110 localplayer.cam_velocity_constant_smooth = vg_lerpf(
111 localplayer.cam_velocity_constant_smooth,
112 localplayer.cam_velocity_constant,
113 vg.time_frame_delta * 8.0f );
114
115 enum camera_mode target_mode = cc->camera_mode;
116
117 if( localplayer.subsystem == k_player_subsystem_dead )
118 target_mode = k_cam_thirdperson;
119
120 cc->camera_type_blend =
121 vg_lerpf( cc->camera_type_blend,
122 (target_mode == k_cam_firstperson)? 1.0f: 0.0f,
123 5.0f * vg.time_frame_delta );
124
125 v3_lerp( cc->fpv_viewpoint_smooth, cc->fpv_viewpoint,
126 vg.time_frame_delta * 8.0f, cc->fpv_viewpoint_smooth );
127
128 v3_lerp( cc->fpv_offset_smooth, cc->fpv_offset,
129 vg.time_frame_delta * 8.0f, cc->fpv_offset_smooth );
130
131 v3_lerp( cc->tpv_offset_smooth, cc->tpv_offset,
132 vg.time_frame_delta * 8.0f, cc->tpv_offset_smooth );
133
134 /* fov -- simple blend */
135 float fov_skate = vg_lerpf( 97.0f, 135.0f, k_fov ),
136 fov_walk = vg_lerpf( 90.0f, 110.0f, k_fov );
137
138 localplayer.cam.fov = vg_lerpf( fov_walk, fov_skate, cc->camera_type_blend );
139
140 /*
141 * first person camera
142 */
143
144 /* position */
145 v3f fpv_pos, fpv_offset;
146 m4x3_mulv( localplayer.final_mtx[ localplayer.id_head-1 ],
147 cc->fpv_viewpoint_smooth, fpv_pos );
148 m3x3_mulv( localplayer.rb.to_world, cc->fpv_offset_smooth, fpv_offset );
149 v3_add( fpv_offset, fpv_pos, fpv_pos );
150
151 /* angles */
152 v3f velocity_angles;
153 v3_lerp( cc->cam_velocity_smooth, localplayer.rb.v, 4.0f*vg.time_frame_delta,
154 cc->cam_velocity_smooth );
155
156 v3_angles( cc->cam_velocity_smooth, velocity_angles );
157 velocity_angles[1] *= localplayer.cam_velocity_coefficient_smooth;
158 velocity_angles[1] += localplayer.cam_velocity_constant_smooth;
159
160 float inf_fpv = localplayer.cam_velocity_influence_smooth *
161 cc->camera_type_blend,
162 inf_tpv = localplayer.cam_velocity_influence_smooth *
163 (1.0f-cc->camera_type_blend);
164
165 vg_camera_lerp_angles( localplayer.angles, velocity_angles,
166 inf_fpv,
167 localplayer.angles );
168
169 /*
170 * Third person camera
171 */
172
173 /* no idea what this technique is called, it acts like clamped position based
174 * on some derivative of where the final camera would end up ....
175 *
176 * it is done in the local basis then transformed back */
177
178 v3f future;
179 v3_muls( localplayer.rb.v, 0.4f*vg.time_frame_delta, future );
180
181 v3f camera_follow_dir =
182 { -sinf( localplayer.angles[0] ) * cosf( localplayer.angles[1] ),
183 sinf( localplayer.angles[1] ),
184 cosf( localplayer.angles[0] ) * cosf( localplayer.angles[1] ) };
185
186 v3f v0;
187 v3_sub( camera_follow_dir, future, v0 );
188
189 v3f follow_angles;
190 v3_copy( localplayer.angles, follow_angles );
191 follow_angles[0] = atan2f( -v0[0], v0[2] );
192 follow_angles[1] = 0.3f + velocity_angles[1] * 0.2f;
193
194 float ya = atan2f( -cc->cam_velocity_smooth[1], 30.0f );
195
196 follow_angles[1] = 0.3f + ya;
197 vg_camera_lerp_angles( localplayer.angles, follow_angles,
198 inf_tpv,
199 localplayer.angles );
200
201 v3f pco;
202 v4f pq;
203 rb_extrapolate( &localplayer.rb, pco, pq );
204 v3_muladds( pco, localplayer.holdout_pose.root_co,
205 localplayer.holdout_time, pco );
206 v3_lerp( cc->tpv_lpf, pco, 20.0f*vg.time_frame_delta, cc->tpv_lpf );
207
208 /* now move into world */
209 v3f tpv_pos, tpv_offset, tpv_origin;
210
211 /* TODO: whats up with CC and not CC but both sets of variables are doing
212 * the same ideas just saved in different places?
213 */
214 /* origin */
215 q_mulv( pq, cc->tpv_offset_smooth, tpv_origin );
216 v3_add( tpv_origin, cc->tpv_lpf, tpv_origin );
217
218 /* offset */
219 v3_muls( camera_follow_dir, localplayer.cam_dist_smooth, tpv_offset );
220 v3_muladds( tpv_offset, cc->cam_velocity_smooth, -0.025f, tpv_offset );
221
222 v3_add( tpv_origin, tpv_offset, tpv_pos );
223
224 /*
225 * Blend cameras
226 */
227 v3_lerp( tpv_pos, fpv_pos, cc->camera_type_blend, localplayer.cam.pos );
228 v3_copy( localplayer.angles, localplayer.cam.angles );
229
230 /* Camera shake */
231 f32 speed = v3_length(localplayer.rb.v),
232 strength = k_cam_shake_strength * speed;
233 localplayer.cam_trackshake +=
234 speed*k_cam_shake_trackspeed*vg.time_frame_delta;
235
236 v2f rnd = {vg_perlin_fract_1d( localplayer.cam_trackshake, 1.0f, 4, 20 ),
237 vg_perlin_fract_1d( localplayer.cam_trackshake, 1.0f, 4, 63 ) };
238 v2_muladds( localplayer.cam.angles, rnd, strength, localplayer.cam.angles );
239
240 v3f Fd, Fs, F;
241 v3_muls( localplayer.cam_land_punch_v, -k_cam_damp, Fd );
242 v3_muls( localplayer.cam_land_punch, -k_cam_spring, Fs );
243 v3_muladds( localplayer.cam_land_punch, localplayer.cam_land_punch_v,
244 vg.time_frame_delta, localplayer.cam_land_punch );
245 v3_add( Fd, Fs, F );
246 v3_muladds( localplayer.cam_land_punch_v, F, vg.time_frame_delta,
247 localplayer.cam_land_punch_v );
248 v3_add( localplayer.cam_land_punch, localplayer.cam.pos,
249 localplayer.cam.pos );
250
251 /* portal transitions */
252 player_camera_portal_correction();
253 }
254
255 static void player_look( v3f angles, float speed ){
256 if( vg_ui.wants_mouse ) return;
257
258 angles[2] = 0.0f;
259
260 v2f mouse_input;
261 v2_copy( vg.mouse_delta, mouse_input );
262 if( k_invert_y ) mouse_input[1] *= -1.0f;
263 v2_muladds( angles, mouse_input, 0.0025f * speed, angles );
264
265 v2f jlook;
266 joystick_state( k_srjoystick_look, jlook );
267
268 angles[0] += jlook[0] * vg.time_frame_delta * 4.0f * speed;
269 float input_y = jlook[1] * vg.time_frame_delta * 4.0f;
270 if( k_invert_y ) input_y *= -1.0f;
271
272 angles[1] += input_y * speed;
273 angles[1] = vg_clampf( angles[1], -VG_PIf*0.5f, VG_PIf*0.5f );
274 }