File: multi_interpolate.h

package info (click to toggle)
freespace2 24.2.0%2Brepack-1
  • links: PTS, VCS
  • area: non-free
  • in suites: forky, sid
  • size: 43,716 kB
  • sloc: cpp: 595,001; ansic: 21,741; python: 1,174; sh: 457; makefile: 248; xml: 181
file content (163 lines) | stat: -rw-r--r-- 6,728 bytes parent folder | download
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
#pragma once

#include "globalincs/pstypes.h"
#include "network/multi_time_manager.h"
#include "physics/physics_state.h"

struct physics_info;

constexpr int PACKET_INFO_LIMIT = 4; // we should never need more than 4 packets to do interpolation.  Overwrite the oldest ones if we do.

typedef struct packet_info {

	int frame;							// this allows us to directly compare one packet to another.  
	int remote_missiontime;				// the remote timestamp that matches this packet.
	physics_snapshot snapshot;			// the received physics info translated into the physics snapshot type for easy interpolation

	packet_info(int frame_in = 0, int time_in = 0, const vec3d* position_in = &vmd_zero_vector, const vec3d* velocity_in = &vmd_zero_vector, 
		const vec3d* rotational_velocity_in = &vmd_zero_vector, const vec3d* desired_velocity_in = &vmd_zero_vector, const vec3d* desired_rotational_velocity_in = &vmd_zero_vector,
		const angles* angles_in = &vmd_zero_angles) 
	{	
		frame = frame_in;
		remote_missiontime = time_in;
		snapshot.position = *position_in;
		snapshot.velocity = *velocity_in;
		snapshot.rotational_velocity = *rotational_velocity_in;
		snapshot.desired_velocity = *desired_velocity_in;
		snapshot.desired_rotational_velocity = *desired_rotational_velocity_in;
		vm_angles_2_matrix(&snapshot.orientation, angles_in);
	}

} packet_info;

// the real center of the new interpolation code.  When a packet is received, its frame is used as the key in the unordered_map _packets
// those keys are kept in _received_frames
class interpolation_manager {
private:
	int _upcoming_packet_index;			// what packet should we look at as the next packet.  -1 if we do not yet have enough packets.
	int _prev_packet_index;				// what was the last packet? This and Upcoming are both idices into the _packets vector. 
	int _local_skip_forward;			// TODO: Use this? Used on the server if a client is inexplicably ahead of us.
	bool _simulation_mode;				// are we currently simulating as if this were a normal ship?
	bool _packets_expended;				// have we used up all packets while interpolating?
	SCP_vector<packet_info> _packets;	// all the info from the position/orientation portion of packets that we care to keep
	int _source_player_index;

	void reassess_packet_index(vec3d* pos, matrix* ori, physics_info* pip);		// for finding which packets from within _packets we should use
	void replace_packet(int index, vec3d* pos, matrix* orient, physics_info* pip);	// a function that acts as a workaround, when coming out of simulation_mode

	// Frame numbers that helps us figure out if we should ignore new information coming from the server because
	// we already received a newer packet than this one for that type of info.
	int _hull_comparison_frame;						// what frame was the last hull information received?
	int _shields_comparison_frame;					// what frame was the last shield information received?
	SCP_vector<std::pair<int,int>> _subsystems_comparison_frame;	// what frame was the last subsystem information received? (for each subsystem) First is health, second is animation
	int _ai_comparison_frame;						// what frame was the last ai information received?

public:

	// adds a new packet, whilst also manually sorting the relevant entries
	void add_packet(int objnum, int frame, int time_delta, vec3d* position, vec3d* velocity, vec3d* rotational_velocity, vec3d* desired_velocity, vec3d* desired_rotational_velocity, angles* angles, int player_index);
	void interpolate_main(vec3d* pos, matrix* ori, physics_info* pip, vec3d* last_pos, matrix* last_orient, vec3d* gravity, bool player_ship);
	void reinterpolate_previous(TIMESTAMP stamp, int prev_packet_index, int next_packet_index,  vec3d& position, matrix& orientation, vec3d& velocity, vec3d& rotational_velocity);

	int get_hull_comparison_frame() { return _hull_comparison_frame; }
	int get_shields_comparison_frame() { return _shields_comparison_frame; }
	
	int get_subsystem_health_frame(int i) 
	{ 
		if (i < static_cast<int>(_subsystems_comparison_frame.size()) && i >= 0) {
			return _subsystems_comparison_frame[i].first; 
		} // if it somehow got passed nonsense, chances are what it is is trying to read is nonsense, and INT_MAX will keep it from doing anything crazy.
		else {
			return INT_MAX;
		}
	}

	int get_subsystem_animation_frame(int i) {
		if (i < static_cast<int>(_subsystems_comparison_frame.size()) && i >= 0) {
			return _subsystems_comparison_frame[i].second; 
		} // if it somehow got passed nonsense, chances are what it is is trying to read is nonsense, and INT_MAX will keep it from doing anything crazy.
		else {
			return INT_MAX;
		}
	}


	int get_ai_comparison_frame() { return _ai_comparison_frame; }

	void set_hull_comparison_frame(int frame) { _hull_comparison_frame = frame; }
	void set_shields_comparison_frame(int frame) { _shields_comparison_frame = frame; }

	void set_subsystem_health_frame(int i, int frame)
	{ 
		if (i < static_cast<int>(_subsystems_comparison_frame.size()) && i >= 0) {
			_subsystems_comparison_frame[i].first = frame;
		} 
	}

	void set_subsystem_animation_frame(int i, int frame)
	{
		if (i < static_cast<int>(_subsystems_comparison_frame.size()) && i >= 0) {
			_subsystems_comparison_frame[i].second = frame;
		} 
	}

	void set_ai_comparison_frame(int frame) { _ai_comparison_frame = frame; }

	void force_interpolation_mode() { _simulation_mode = true; }

	void reset(int subsystem_count) 
	{
		if (!(Game_mode & GM_MULTIPLAYER)){
			return;
		}

		_packets.clear();
		_packets.reserve(PACKET_INFO_LIMIT * 2);
		_upcoming_packet_index = -1;
		_prev_packet_index = -1;
		_simulation_mode = false;
		_packets_expended = false;
		_local_skip_forward = 0;
		_hull_comparison_frame = -1;
		_shields_comparison_frame = -1;
		_source_player_index = -1;


		_subsystems_comparison_frame.clear();

		for (int i = 0; i < subsystem_count; i++) {
			_subsystems_comparison_frame.emplace_back(-1, -1);
		}

		_ai_comparison_frame = -1;
	}

	void clean_up() 
	{
		_packets.clear();
		_packets.shrink_to_fit();
		_subsystems_comparison_frame.clear();
		_subsystems_comparison_frame.shrink_to_fit();
	}

	interpolation_manager()
	{
		_upcoming_packet_index = -1;
		_prev_packet_index = -1;
		_simulation_mode = false;
		_packets_expended = false;
		_local_skip_forward = 0;
		_hull_comparison_frame = -1;
		_shields_comparison_frame = -1;
		_ai_comparison_frame = -1;
		_source_player_index = -1;
	}
};

void multi_interpolate_clear_all();

void multi_interpolate_clear_helper(int objnum);

void interpolate_main_helper(int objnum, vec3d* pos, matrix* ori, physics_info* pip, vec3d* last_pos, matrix* last_orient, vec3d* gravity, bool player_ship);

extern SCP_unordered_map<int, interpolation_manager> Interp_info;