performance measurements
[carveJwlIkooP6JGAAIwe30JlM.git] / vehicle.c
1 #ifndef VEHICLE_C
2 #define VEHICLE_C
3
4 #include "vehicle.h"
5
6 static int spawn_car( int argc, const char *argv[] ){
7 v3f ra, rb, rx;
8 v3_copy( skaterift.cam.pos, ra );
9 v3_muladds( ra, skaterift.cam.transform[2], -10.0f, rb );
10
11 float t;
12 if( spherecast_world( world_current_instance(), ra, rb,
13 gzoomer.obj.inf.sphere.radius, &t, rx, 0 ) != -1 )
14 {
15 v3_lerp( ra, rb, t, gzoomer.obj.rb.co );
16 gzoomer.obj.rb.co[1] += 4.0f;
17 q_axis_angle( gzoomer.obj.rb.q, (v3f){1.0f,0.0f,0.0f}, 0.001f );
18 v3_zero( gzoomer.obj.rb.v );
19 v3_zero( gzoomer.obj.rb.w );
20
21 rb_update_transform( &gzoomer.obj.rb );
22 gzoomer.alive = 1;
23
24 vg_success( "Spawned car\n" );
25 }
26 else{
27 vg_error( "Can't spawn here\n" );
28 }
29
30 return 0;
31 }
32
33 static void vehicle_init(void)
34 {
35 q_identity( gzoomer.obj.rb.q );
36 v3_zero( gzoomer.obj.rb.w );
37 v3_zero( gzoomer.obj.rb.v );
38 v3_zero( gzoomer.obj.rb.co );
39 rb_init_object( &gzoomer.obj );
40
41 VG_VAR_F32( k_car_spring, flags=VG_VAR_PERSISTENT );
42 VG_VAR_F32( k_car_spring_damp, flags=VG_VAR_PERSISTENT );
43 VG_VAR_F32( k_car_spring_length, flags=VG_VAR_PERSISTENT );
44 VG_VAR_F32( k_car_wheel_radius, flags=VG_VAR_PERSISTENT );
45 VG_VAR_F32( k_car_friction_lat, flags=VG_VAR_PERSISTENT );
46 VG_VAR_F32( k_car_friction_roll, flags=VG_VAR_PERSISTENT );
47 VG_VAR_F32( k_car_drive_force, flags=VG_VAR_PERSISTENT );
48 VG_VAR_F32( k_car_air_resistance,flags=VG_VAR_PERSISTENT );
49 VG_VAR_F32( k_car_downforce, flags=VG_VAR_PERSISTENT );
50
51 VG_VAR_I32( gzoomer.inside );
52
53 vg_console_reg_cmd( "spawn_car", spawn_car, NULL );
54
55 v3_copy((v3f){ -1.0f, -0.25f, -1.5f }, gzoomer.wheels_local[0] );
56 v3_copy((v3f){ 1.0f, -0.25f, -1.5f }, gzoomer.wheels_local[1] );
57 v3_copy((v3f){ -1.0f, -0.25f, 1.5f }, gzoomer.wheels_local[2] );
58 v3_copy((v3f){ 1.0f, -0.25f, 1.5f }, gzoomer.wheels_local[3] );
59 }
60
61 static void vehicle_wheel_force( int index )
62 {
63 v3f pa, pb, n;
64 m4x3_mulv( gzoomer.obj.rb.to_world, gzoomer.wheels_local[index], pa );
65 v3_muladds( pa, gzoomer.obj.rb.to_world[1], -k_car_spring_length, pb );
66
67
68 #if 1
69 float t;
70 if( spherecast_world( world_current_instance(), pa, pb,
71 k_car_wheel_radius, &t, n, 0 ) == -1 )
72 { t = 1.0f;
73 }
74
75 #else
76
77 v3f dir;
78 v3_muls( gzoomer.rb.up, -1.0f, dir );
79
80 ray_hit hit;
81 hit.dist = k_car_spring_length;
82 ray_world( pa, dir, &hit );
83
84 float t = hit.dist / k_car_spring_length;
85
86 #endif
87
88 v3f pc;
89 v3_lerp( pa, pb, t, pc );
90
91 m4x3f mtx;
92 m3x3_copy( gzoomer.obj.rb.to_world, mtx );
93 v3_copy( pc, mtx[3] );
94 vg_line_sphere( mtx, k_car_wheel_radius, VG__BLACK );
95 vg_line( pa, pc, VG__WHITE );
96 v3_copy( pc, gzoomer.wheels[index] );
97
98 if( t < 1.0f ){
99 /* spring force */
100 float Fv = (1.0f-t) * k_car_spring*k_rb_delta;
101
102 v3f delta;
103 v3_sub( pa, gzoomer.obj.rb.co, delta );
104
105 v3f rv;
106 v3_cross( gzoomer.obj.rb.w, delta, rv );
107 v3_add( gzoomer.obj.rb.v, rv, rv );
108
109 Fv += v3_dot( rv, gzoomer.obj.rb.to_world[1] )
110 * -k_car_spring_damp*k_rb_delta;
111
112 /* scale by normal incident */
113 Fv *= v3_dot( n, gzoomer.obj.rb.to_world[1] );
114
115 v3f F;
116 v3_muls( gzoomer.obj.rb.to_world[1], Fv, F );
117
118 rb_linear_impulse( &gzoomer.obj.rb, delta, F );
119
120 /* friction vectors
121 * -------------------------------------------------------------*/
122 v3f tx, ty;
123
124 if( index <= 1 )
125 v3_cross( gzoomer.steerv, n, tx );
126 else
127 v3_cross( n, gzoomer.obj.rb.to_world[2], tx );
128 v3_cross( tx, n, ty );
129
130 v3_copy( tx, gzoomer.tangent_vectors[ index ][0] );
131 v3_copy( ty, gzoomer.tangent_vectors[ index ][1] );
132
133 gzoomer.normal_forces[ index ] = Fv;
134 gzoomer.tangent_forces[ index ][0] = 0.0f;
135 gzoomer.tangent_forces[ index ][1] = 0.0f;
136
137 /* orient inverse inertia tensors */
138 v3f raW;
139 m3x3_mulv( gzoomer.obj.rb.to_world, gzoomer.wheels_local[index], raW );
140
141 v3f raCtx, raCtxI, raCty, raCtyI;
142 v3_cross( tx, raW, raCtx );
143 v3_cross( ty, raW, raCty );
144 m3x3_mulv( gzoomer.obj.rb.iIw, raCtx, raCtxI );
145 m3x3_mulv( gzoomer.obj.rb.iIw, raCty, raCtyI );
146
147 gzoomer.tangent_mass[index][0] = gzoomer.obj.rb.inv_mass;
148 gzoomer.tangent_mass[index][0] += v3_dot( raCtx, raCtxI );
149 gzoomer.tangent_mass[index][0] = 1.0f/gzoomer.tangent_mass[index][0];
150
151 gzoomer.tangent_mass[index][1] = gzoomer.obj.rb.inv_mass;
152 gzoomer.tangent_mass[index][1] += v3_dot( raCty, raCtyI );
153 gzoomer.tangent_mass[index][1] = 1.0f/gzoomer.tangent_mass[index][1];
154
155 /* apply drive force */
156 if( index >= 2 ){
157 v3_muls( ty, -gzoomer.drive * k_car_drive_force * k_rb_delta, F );
158 rb_linear_impulse( &gzoomer.obj.rb, raW, F );
159 }
160 }
161 else{
162 gzoomer.normal_forces[ index ] = 0.0f;
163 gzoomer.tangent_forces[ index ][0] = 0.0f;
164 gzoomer.tangent_forces[ index ][1] = 0.0f;
165 }
166 }
167
168 static void vehicle_solve_friction(void)
169 {
170 rigidbody *rb = &gzoomer.obj.rb;
171 for( int i=0; i<4; i++ ){
172 v3f raW;
173 m3x3_mulv( rb->to_world, gzoomer.wheels_local[i], raW );
174
175 v3f rv;
176 v3_cross( rb->w, raW, rv );
177 v3_add( rb->v, rv, rv );
178
179 float fx = k_car_friction_lat * gzoomer.normal_forces[i],
180 fy = k_car_friction_roll * gzoomer.normal_forces[i],
181 vtx = v3_dot( rv, gzoomer.tangent_vectors[i][0] ),
182 vty = v3_dot( rv, gzoomer.tangent_vectors[i][1] ),
183 lambdax = gzoomer.tangent_mass[i][0] * -vtx,
184 lambday = gzoomer.tangent_mass[i][1] * -vty;
185
186 float tempx = gzoomer.tangent_forces[i][0],
187 tempy = gzoomer.tangent_forces[i][1];
188 gzoomer.tangent_forces[i][0] = vg_clampf( tempx + lambdax, -fx, fx );
189 gzoomer.tangent_forces[i][1] = vg_clampf( tempy + lambday, -fy, fy );
190 lambdax = gzoomer.tangent_forces[i][0] - tempx;
191 lambday = gzoomer.tangent_forces[i][1] - tempy;
192
193 v3f impulsex, impulsey;
194 v3_muls( gzoomer.tangent_vectors[i][0], lambdax, impulsex );
195 v3_muls( gzoomer.tangent_vectors[i][1], lambday, impulsey );
196 rb_linear_impulse( rb, raW, impulsex );
197 rb_linear_impulse( rb, raW, impulsey );
198 }
199 }
200
201 static void vehicle_update_fixed(void)
202 {
203 if( !gzoomer.alive )
204 return;
205
206 rigidbody *rb = &gzoomer.obj.rb;
207
208 v3_muls( rb->to_world[2], -cosf(gzoomer.steer), gzoomer.steerv );
209 v3_muladds( gzoomer.steerv, rb->to_world[0],
210 sinf(gzoomer.steer), gzoomer.steerv );
211
212 /* apply air resistance */
213 v3f Fair, Fdown;
214
215 v3_muls( rb->v, -k_car_air_resistance, Fair );
216 v3_muls( rb->to_world[1], -fabsf(v3_dot( rb->v, rb->to_world[2] )) *
217 k_car_downforce, Fdown );
218
219 v3_muladds( rb->v, Fair, k_rb_delta, rb->v );
220 v3_muladds( rb->v, Fdown, k_rb_delta, rb->v );
221
222 for( int i=0; i<4; i++ )
223 vehicle_wheel_force( i );
224
225 rb_ct manifold[64];
226 int len = rb_sphere__scene( rb->to_world, &gzoomer.obj.inf.sphere, NULL,
227 &world_current_instance()->rb_geo.inf.scene,
228 manifold, 0 );
229 for( int j=0; j<len; j++ ){
230 manifold[j].rba = rb;
231 manifold[j].rbb = &world_current_instance()->rb_geo.rb;
232 }
233 rb_manifold_filter_coplanar( manifold, len, 0.05f );
234
235 if( len > 1 ){
236 rb_manifold_filter_backface( manifold, len );
237 rb_manifold_filter_joint_edges( manifold, len, 0.05f );
238 rb_manifold_filter_pairs( manifold, len, 0.05f );
239 }
240 len = rb_manifold_apply_filtered( manifold, len );
241
242 rb_presolve_contacts( manifold, len );
243 for( int i=0; i<8; i++ ){
244 rb_solve_contacts( manifold, len );
245 vehicle_solve_friction();
246 }
247
248 rb_iter( rb );
249 rb_update_transform( rb );
250 }
251
252 static void vehicle_update_post(void)
253 {
254 if( !gzoomer.alive )
255 return;
256
257 rb_object_debug( &gzoomer.obj, VG__WHITE );
258
259 /* draw friction vectors */
260 v3f p0, px, py;
261
262 for( int i=0; i<4; i++ ){
263 v3_copy( gzoomer.wheels[i], p0 );
264 v3_muladds( p0, gzoomer.tangent_vectors[i][0], 0.5f, px );
265 v3_muladds( p0, gzoomer.tangent_vectors[i][1], 0.5f, py );
266
267 vg_line( p0, px, VG__RED );
268 vg_line( p0, py, VG__GREEN );
269 }
270 }
271
272 #endif /* VEHICLE_H */