1 //
2 //  SuperTuxKart - a fun racing game with go-kart
3 //  Copyright (C) 2018 SuperTuxKart-Team
4 //
5 //  This program is free software; you can redistribute it and/or
6 //  modify it under the terms of the GNU General Public License
7 //  as published by the Free Software Foundation; either version 3
8 //  of the License, or (at your option) any later version.
9 //
10 //  This program is distributed in the hope that it will be useful,
11 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 //  GNU General Public License for more details.
14 //
15 //  You should have received a copy of the GNU General Public License
16 //  along with this program; if not, write to the Free Software
17 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 
19 /*! \file smooth_network_body.hpp
20  *  \brief This class help to smooth the graphicial transformation of network
21  *  controlled object. In case there is any difference between server and
22  *  client predicted values, instead of showing the server one immediately,
23  *  it will interpolate between them with an extrapolated value from the old
24  *  predicted values stored in m_adjust_control_point estimated by current
25  *  speed of object.
26  */
27 
28 #ifndef HEADER_SMOOTH_NETWORK_BODY_HPP
29 #define HEADER_SMOOTH_NETWORK_BODY_HPP
30 
31 #include "utils/log.hpp"
32 #include "utils/vec3.hpp"
33 
34 #include "LinearMath/btTransform.h"
35 
36 #include <utility>
37 
38 class SmoothNetworkBody
39 {
40 private:
41     enum SmoothingState
42     {
43         SS_NONE = 0,
44         SS_TO_ADJUST,
45         SS_TO_REAL
46     };
47 
48     /** Client prediction in networked games might cause the visual
49      *  and physical position to be different. For visual smoothing
50      *  these variable accumulate the error and reduces it over time. */
51     std::pair<Vec3, btQuaternion> m_start_smoothing_postion,
52         m_adjust_position;
53 
54     Vec3 m_adjust_control_point;
55 
56     std::pair<btTransform, Vec3> m_prev_position_data;
57 
58     btTransform m_smoothed_transform;
59 
60     float m_adjust_time, m_adjust_time_dt;
61 
62     SmoothingState m_smoothing;
63 
64     bool m_enabled;
65 
66     bool m_smooth_rotation;
67 
68     bool m_adjust_vertical_offset;
69 
70     float m_min_adjust_length, m_max_adjust_length, m_min_adjust_speed,
71         m_max_adjust_time, m_adjust_length_threshold;
72 
73 public:
74     SmoothNetworkBody(bool enable = false);
75     // ------------------------------------------------------------------------
~SmoothNetworkBody()76     virtual ~SmoothNetworkBody() {}
77     // ------------------------------------------------------------------------
reset()78     void reset()
79     {
80         m_smoothed_transform = btTransform(btQuaternion(0.0f, 0.0f, 0.0f, 1.0f));
81         m_start_smoothing_postion = m_adjust_position =
82             std::make_pair(Vec3(0.0f, 0.0f, 0.0f),
83             btQuaternion(0.0f, 0.0f, 0.0f, 1.0f));
84         m_prev_position_data = std::make_pair(m_smoothed_transform, Vec3());
85         m_smoothing = SS_NONE;
86         m_adjust_time = m_adjust_time_dt = 0.0f;
87     }
88     // ------------------------------------------------------------------------
setEnable(bool val)89     void setEnable(bool val)                               { m_enabled = val; }
90     // ------------------------------------------------------------------------
isEnabled() const91     bool isEnabled() const                                { return m_enabled; }
92     // ------------------------------------------------------------------------
setSmoothRotation(bool val)93     void setSmoothRotation(bool val)               { m_smooth_rotation = val; }
94     // ------------------------------------------------------------------------
setAdjustVerticalOffset(bool val)95     void setAdjustVerticalOffset(bool val)  { m_adjust_vertical_offset = val; }
96     // ------------------------------------------------------------------------
97     void prepareSmoothing(const btTransform& current_transform,
98                           const Vec3& current_velocity);
99     // ------------------------------------------------------------------------
100     void checkSmoothing(const btTransform& current_transform,
101                         const Vec3& current_velocity);
102     // ------------------------------------------------------------------------
103     void updateSmoothedGraphics(const btTransform& current_transform,
104                                 const Vec3& current_velocity,
105                                 float dt);
106     // ------------------------------------------------------------------------
setSmoothedTransform(const btTransform & t)107     void setSmoothedTransform(const btTransform& t)
108                                                   { m_smoothed_transform = t; }
109     // ------------------------------------------------------------------------
getSmoothedTrans() const110     const btTransform& getSmoothedTrans() const
111                                                { return m_smoothed_transform; }
112     // ------------------------------------------------------------------------
getSmoothedXYZ() const113     const Vec3& getSmoothedXYZ() const
114                             { return (Vec3&)m_smoothed_transform.getOrigin(); }
115     // ------------------------------------------------------------------------
setMinAdjustLength(float val)116     void setMinAdjustLength(float val)           { m_min_adjust_length = val; }
117     // ------------------------------------------------------------------------
setMaxAdjustLength(float val)118     void setMaxAdjustLength(float val)           { m_max_adjust_length = val; }
119     // ------------------------------------------------------------------------
setMinAdjustSpeed(float val)120     void setMinAdjustSpeed(float val)             { m_min_adjust_speed = val; }
121     // ------------------------------------------------------------------------
setMaxAdjustTime(float val)122     void setMaxAdjustTime(float val)               { m_max_adjust_time = val; }
123     // ------------------------------------------------------------------------
setAdjustLengthThreshold(float val)124     void setAdjustLengthThreshold(float val)
125                                            { m_adjust_length_threshold = val; }
126 
127 };
128 
129 #endif // HEADER_SMOOTH_NETWORK_BODY_HPP
130