summaryrefslogtreecommitdiff
path: root/vphysics/physics_airboat.h
blob: c1f649cdac1df46100545b8d09a593b5d9795d4b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: 
//
//=============================================================================//

#ifndef PHYSICS_AIRBOAT_H
#define PHYSICS_AIRBOAT_H
#ifdef _WIN32
#pragma once
#endif

#include "ivp_controller.hxx"
#include "ivp_car_system.hxx"


class IPhysicsObject;
class IVP_Ray_Solver_Template;
class IVP_Ray_Hit;
class IVP_Event_Sim;


#define IVP_RAYCAST_AIRBOAT_MAX_WHEELS			4


//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
class IVP_Raycast_Airboat_Wheel
{
public:

    // static section
    IVP_U_Float_Point	hp_cs;										// hard point core system projected on y plane
	IVP_U_Float_Point	raycast_start_cs;							// ray cast start position
	IVP_U_Float_Point	raycast_dir_cs;
	IVP_FLOAT			raycast_length;

    IVP_U_Float_Point	spring_direction_cs;						// spring direction in core-space
    IVP_FLOAT			distance_orig_hp_to_hp;						// distance hp is moved by projecting it onto the y - plane
    IVP_FLOAT			spring_len;  								// == pretension + distance_orig_hp_to_hp
    IVP_FLOAT			spring_constant;							// shock at wheel spring constant
    IVP_FLOAT			spring_damp_relax;							// shock at wheel spring dampening during relaxation
    IVP_FLOAT			spring_damp_compress;						// shock at wheel spring dampening during compression

    IVP_FLOAT			max_rotation_speed;							// max rotational speed of the wheel
    
    IVP_FLOAT			wheel_radius;								// wheel radius
    IVP_FLOAT			inv_wheel_radius;							// inverse wheel radius
    IVP_FLOAT			friction_of_wheel;							// wheel friction
    
    // dynamic section
    IVP_FLOAT			torque;										// torque applied to wheel
    IVP_BOOL			wheel_is_fixed;								// eg. handbrake (fixed = stationary)
    IVP_U_Float_Point	axis_direction_cs;							// axle direction in core-space
    IVP_FLOAT			angle_wheel;								// wheel angle
    IVP_FLOAT			wheel_angular_velocity;						// angular velocity of wheel
    
    // out
    IVP_U_Float_Point	surface_speed_of_wheel_on_ground_ws;		// actual speed in world-space
    IVP_FLOAT			pressure;									// force from gravity, mass of car, stabilizers, etc. on wheel
    IVP_FLOAT			raycast_dist;								// raycast distance to impact for wheel
};


//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
class IVP_Raycast_Airboat_Impact
{
public:

    IVP_FLOAT			friction_value;								// combined (multiply) frictional value of impact surface and wheel
    IVP_FLOAT			stabilizer_force;							// force on wheel due to axle stabilization
    IVP_Real_Object		*moveable_object_hit_by_ray;				// moveable physics object hit by raycast

	IVP_U_Float_Point	raycast_dir_ws;								// raycast direction in world-space
    IVP_U_Float_Point	spring_direction_ws;						// spring direction (raycast for impact direction) in world-space
    IVP_U_Float_Point	surface_speed_wheel_ws;						// wheel speed in world-space
    IVP_U_Float_Point	projected_surface_speed_wheel_ws;			// ???
    IVP_U_Float_Point	axis_direction_ws;							// axle direction in world-space
    IVP_U_Float_Point	projected_axis_direction_ws;				// ???

    IVP_FLOAT			forces_needed_to_drive_straight;			// forces need to keep the vehicle driving straight (attempt and directional wheel friction)
    IVP_FLOAT			inv_normal_dot_dir;							// ???

	// Impact information.
	IVP_BOOL			bImpact;							// Had an impact?
	IVP_BOOL			bImpactWater;						// Impact with water?
	IVP_BOOL			bInWater;							// Point in water?
	IVP_U_Point			vecImpactPointWS;					// Impact point in world-space.
	IVP_U_Float_Point	vecImpactNormalWS;					// Impact normal in world-space.
	IVP_FLOAT			flDepth;							// Distance to water surface.
	IVP_FLOAT			flFriction;							// Friction at impact point.
	IVP_FLOAT			flDampening;						// Dampening at surface.
	int					nSurfaceProps;						// Surface property!
};


//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
class IVP_Raycast_Airboat_Axle 
{
public:

    IVP_FLOAT			stabilizer_constant;						// axle (for wheels) stabilizer constant
};


//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
class IVP_Controller_Raycast_Airboat_Vector_of_Cores_1: public IVP_U_Vector<IVP_Core> 
{
    void *elem_buffer[1];

public:

    IVP_Controller_Raycast_Airboat_Vector_of_Cores_1();
};


//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
class CPhysics_Airboat : public IVP_Car_System, protected IVP_Controller_Dependent  
{

public:

    CPhysics_Airboat( IVP_Environment *env, const IVP_Template_Car_System *t, IPhysicsGameTrace *pGameTrace );
    virtual ~CPhysics_Airboat();

    void update_wheel_positions( void ) {}
	void SetWheelFriction( int iWheel, float flFriction );

	IPhysicsObject *GetWheel( int index );

	virtual const char *get_controller_name() { return "sys:airboat"; }

protected:

	void InitAirboat( const IVP_Template_Car_System *pCarSystem );
	float GetWaterDepth( Ray_t *pGameRay, IPhysicsObject *pPhysAirboat );

	// Purpose: Deconstructor
	void PerformFrictionNotification( float flEliminatedEnergy, float dt, int nSurfaceProp, IPhysicsCollisionData *pCollisionData );

	void do_raycasts_gameside( int nRaycastCount, IVP_Ray_Solver_Template *pRays, IVP_Raycast_Airboat_Impact *pImpacts );
	void pre_raycasts_gameside( int nRaycastCount, IVP_Ray_Solver_Template *pRays, Ray_t *pGameRays, IVP_Raycast_Airboat_Impact *pImpacts );

    IVP_Real_Object		*m_pWheels[IVP_RAYCAST_AIRBOAT_MAX_WHEELS];
	IPhysicsGameTrace	*m_pGameTrace;

public:

	// Steering
    void							do_steering_wheel(IVP_POS_WHEEL wheel_pos, IVP_FLOAT s_angle);						// called by do_steering()

    // Car Adjustment
    void							change_spring_constant(IVP_POS_WHEEL pos, IVP_FLOAT spring_constant);				// [Newton/meter]
    void							change_spring_dampening(IVP_POS_WHEEL pos, IVP_FLOAT spring_dampening);				// when spring is relaxing spring
    void							change_spring_dampening_compression(IVP_POS_WHEEL pos, IVP_FLOAT spring_dampening); // [Newton/meter] for compressing spring
    void							change_max_body_force(IVP_POS_WHEEL , IVP_FLOAT mforce) {}
    void							change_spring_pre_tension(IVP_POS_WHEEL pos, IVP_FLOAT pre_tension_length);
	void							change_spring_length(IVP_POS_WHEEL pos, IVP_FLOAT spring_length);

    void							change_stabilizer_constant(IVP_POS_AXIS pos, IVP_FLOAT stabi_constant);				// [Newton/meter]
	void							change_fast_turn_factor( IVP_FLOAT fast_turn_factor_ );								// not implemented for raycasts
    void							change_wheel_torque(IVP_POS_WHEEL pos, IVP_FLOAT torque);
	IVP_FLOAT						get_wheel_torque(IVP_POS_WHEEL wheel_nr);
    
	void							update_throttle( IVP_FLOAT flThrottle );

    void							update_body_countertorque() {}
    
    void							change_body_downforce(IVP_FLOAT force);												// extra force to keep flipped objects flipped over

    void							fix_wheel( IVP_POS_WHEEL, IVP_BOOL stop_wheel );									// stop wheel completely (e.g. handbrake )
	void							change_friction_of_wheel( IVP_POS_WHEEL pos, IVP_FLOAT friction );
	void							set_powerslide( float frontAccel, float rearAccel )	{}

    // Car Info
    IVP_DOUBLE						get_body_speed(IVP_COORDINATE_INDEX idx_z = IVP_INDEX_Z);							// km/h in 'z' direction
    IVP_DOUBLE						get_wheel_angular_velocity(IVP_POS_WHEEL);
    IVP_DOUBLE						get_orig_front_wheel_distance();
    IVP_DOUBLE						get_orig_axles_distance();
	void							get_skid_info( IVP_Wheel_Skid_Info *array_of_skid_info_out);
    
    void							get_wheel_position(IVP_U_Point *position_ws_out, IVP_U_Quat *direction_ws_out);
  
    // Methods: 2nd Level, based on primitives
    virtual void					do_steering(IVP_FLOAT steering_angle_in, bool bAnalog);											// default implementation updates this->steering_angle

	//
	// Booster (the airboat has no booster). 
	//
	virtual bool IsBoosting(void) { return false; }
    virtual void					set_booster_acceleration( IVP_FLOAT acceleration) {}
    virtual void					activate_booster(IVP_FLOAT thrust, IVP_FLOAT duration, IVP_FLOAT delay) {}
    virtual void					update_booster(IVP_FLOAT delta_time) {}
	virtual IVP_FLOAT				get_booster_delay() { return 0; }
	virtual IVP_FLOAT				get_booster_time_to_go() { return 0; }
    
	// Debug
	void							SetCarSystemDebugData( const IVP_CarSystemDebugData_t &carSystemDebugData );
	void							GetCarSystemDebugData( IVP_CarSystemDebugData_t &carSystemDebugData );

protected:

	IVP_Core						*m_pCore;
	IVP_U_Float_Point				m_vecLocalVelocity;
	float							m_flSpeed;
    IVP_Real_Object					*m_pAirboatBody;			// *car_body

	// Wheels/Axles.
    short							n_wheels;
    short							n_axis;
    short							wheels_per_axis;
    IVP_Raycast_Airboat_Wheel		m_aAirboatWheels[IVP_RAYCAST_AIRBOAT_MAX_WHEELS];		// wheel_of_car
    IVP_Raycast_Airboat_Axle		m_aAirboatAxles[IVP_RAYCAST_AIRBOAT_MAX_WHEELS/2];		// axis_of_car

	// Gravity.
    IVP_FLOAT						gravity_y_direction; //  +/-1
    IVP_U_Float_Point				normized_gravity_ws;
    IVP_FLOAT						extra_gravity;
    
	// Orientation.
    IVP_COORDINATE_INDEX			index_x;
    IVP_COORDINATE_INDEX			index_y;
    IVP_COORDINATE_INDEX			index_z;
    IVP_BOOL						is_left_handed;

	// Speed.
    IVP_FLOAT						max_speed;

	//
    IVP_FLOAT						down_force;
    IVP_FLOAT						down_force_vertical_offset;

    // Steering
    IVP_FLOAT						m_SteeringAngle;
	bool							m_bSteeringReversed;
	bool							m_bAnalogSteering;
	IVP_FLOAT						m_flPrevSteeringAngle;
	IVP_FLOAT						m_flSteerTime;			// Number of seconds we've steered in this direction.

	// Thrust.
	IVP_FLOAT						m_flThrust;

	bool							m_bAirborne;		// Whether we are airborne or not.
	IVP_FLOAT						m_flAirTime;		// How long we've been airborne (if we are).
	bool							m_bWeakJump;		// Set when we become airborne while going slow.

	// Pitch and roll stabilizers.
	IVP_FLOAT						m_flPitchErrorPrev;
	IVP_FLOAT						m_flRollErrorPrev;

	// Debugging!
	IVP_CarSystemDebugData_t		m_CarSystemDebugData;
    
protected:

    IVP_Raycast_Airboat_Wheel		*get_wheel( IVP_POS_WHEEL i );
    IVP_Raycast_Airboat_Axle		*get_axle( IVP_POS_AXIS i );
							
    virtual void			core_is_going_to_be_deleted_event( IVP_Core * );
    virtual IVP_U_Vector<IVP_Core>  *get_associated_controlled_cores( void );
    
    virtual void                    do_simulation_controller(IVP_Event_Sim *,IVP_U_Vector<IVP_Core> *core_list);
    virtual IVP_CONTROLLER_PRIORITY get_controller_priority();

private:

	// Initialization. 
	void							InitRaycastCarEnvironment( IVP_Environment *pEnvironment, const IVP_Template_Car_System *pCarSystemTemplate );
	void							InitRaycastCarBody( const IVP_Template_Car_System *pCarSystemTemplate );
	void							InitRaycastCarWheels( const IVP_Template_Car_System *pCarSystemTemplate );
	void							InitRaycastCarAxes( const IVP_Template_Car_System *pCarSystemTemplate );

	// Raycasts for simulation.
	void							PreRaycasts( IVP_Ray_Solver_Template *pRaySolverTemplates, const IVP_U_Matrix *m_world_f_core, IVP_Raycast_Airboat_Impact *pImpacts );	
	bool							PostRaycasts( IVP_Ray_Solver_Template *pRaySolverTemplates, const IVP_U_Matrix *matWorldFromCore, IVP_Raycast_Airboat_Impact *pImpacts );

	// Simulation.
	void							DoSimulationPontoons( IVP_Raycast_Airboat_Impact *pImpacts, IVP_Event_Sim *pEventSim );
	void							DoSimulationPontoonsGround( IVP_Raycast_Airboat_Wheel *pPontoonPoint, IVP_Raycast_Airboat_Impact *pImpact, IVP_Event_Sim *pEventSim );
	void							DoSimulationPontoonsWater( IVP_Raycast_Airboat_Wheel *pPontoonPoint, IVP_Raycast_Airboat_Impact *pImpact, IVP_Event_Sim *pEventSim );
	void							DoSimulationDrag( IVP_Raycast_Airboat_Impact *pImpacts, IVP_Event_Sim *pEventSim );
	void							DoSimulationTurbine( IVP_Event_Sim *pEventSim );
	void							DoSimulationSteering( IVP_Event_Sim *pEventSim );
	void							DoSimulationKeepUprightPitch( IVP_Raycast_Airboat_Impact *pImpacts, IVP_Event_Sim *pEventSim );
	void							DoSimulationKeepUprightRoll( IVP_Raycast_Airboat_Impact *pImpacts, IVP_Event_Sim *pEventSim );
	void							DoSimulationGravity( IVP_Event_Sim *pEventSim );

	int								CountSurfaceContactPoints( IVP_Raycast_Airboat_Impact *pImpacts );
	void							UpdateAirborneState( IVP_Raycast_Airboat_Impact *pImpacts, IVP_Event_Sim *pEventSim );

	float							ComputeFrontPontoonWaveNoise( int nPontoonIndex, float flSpeedRatio );

	void							CalcImpactPosition( IVP_Ray_Solver_Template *pRaySolver, IVP_Raycast_Airboat_Wheel *pPontoonPoint,
													    IVP_Raycast_Airboat_Impact *pImpacts );

    IVP_Controller_Raycast_Airboat_Vector_of_Cores_1 vector_of_cores;
};

#endif // PHYSICS_AIRBOAT_H