831ce95e9eb34432f8082f7ad9be84ffa6166a7b
[xonotic/xonotic-data.pk3dir.git] / qcsrc / lib / csqcmodel / interpolate.qc
1 /*
2  * Copyright (c) 2011 Rudolf Polzer
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to
6  * deal in the Software without restriction, including without limitation the
7  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8  * sell copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20  * IN THE SOFTWARE.
21  */
22 #include "interpolate.qh"
23
24 // 1 = old, 2 = new
25 .vector iorigin1, iorigin2;
26 .vector ivelocity1, ivelocity2;
27 .vector iforward1, iforward2;
28 .vector iup1, iup2;
29 .vector ivforward1, ivforward2;
30 .vector ivup1, ivup2;
31 .float itime1, itime2;
32 void InterpolateOrigin_Reset(entity this)
33 {
34         this.iflags &= ~IFLAG_INTERNALMASK;
35         this.itime1 = this.itime2 = 0;
36 }
37 void InterpolateOrigin_Note(entity this)
38 {
39         float dt = time - this.itime2;
40
41         int f0 = this.iflags;
42         if (this.iflags & IFLAG_PREVALID) this.iflags |= IFLAG_VALID;
43         else this.iflags |= IFLAG_PREVALID;
44
45         if (this.iflags & IFLAG_ORIGIN)
46         {
47                 this.iorigin1 = this.iorigin2;
48                 this.iorigin2 = this.origin;
49         }
50
51         if ((this.iflags & IFLAG_AUTOANGLES)
52             && this.iorigin2
53             != this.iorigin1) this.angles = vectoangles(this.iorigin2 - this.iorigin1);
54
55         if ((this.iflags & IFLAG_AUTOVELOCITY)
56             && this.itime2
57             != this.itime1) this.velocity = (this.iorigin2 - this.iorigin1) * (1.0 / (this.itime2 - this.itime1));
58
59         if (this.iflags & IFLAG_ANGLES)
60         {
61                 vector forward, right, up;
62                 FIXED_MAKE_VECTORS(this.angles, forward, right, up);
63                 if (f0 & IFLAG_VALID)
64                 {
65                         this.iforward1 = this.iforward2;
66                         this.iup1 = this.iup2;
67                 }
68                 else
69                 {
70                         this.iforward1 = forward;
71                         this.iup1 = up;
72                 }
73                 this.iforward2 = forward;
74                 this.iup2 = up;
75         }
76
77         if (this.iflags & IFLAG_V_ANGLE)
78         {
79                 vector forward, right, up;
80                 FIXED_MAKE_VECTORS(this.v_angle, forward, right, up);
81                 if (f0 & IFLAG_VALID)
82                 {
83                         this.ivforward1 = this.ivforward2;
84                         this.ivup1 = this.ivup2;
85                 }
86                 else
87                 {
88                         this.ivforward1 = forward;
89                         this.ivup1 = up;
90                 }
91                 this.ivforward2 = forward;
92                 this.ivup2 = up;
93         }
94         else if (this.iflags & IFLAG_V_ANGLE_X)
95         {
96                 this.ivforward1_x = this.ivforward2_x;
97                 this.ivforward2_x = this.v_angle.x;
98         }
99
100         if (this.iflags & IFLAG_VELOCITY)
101         {
102                 this.ivelocity1 = this.ivelocity2;
103                 this.ivelocity2 = this.velocity;
104         }
105
106         if (this.iflags & IFLAG_TELEPORTED)
107         {
108                 this.iflags &= ~IFLAG_TELEPORTED;
109                 this.itime1 = this.itime2 = time;  // don't lerp
110         }
111         else if (vdist(this.iorigin2 - this.iorigin1, >, 1000))
112         {
113                 this.itime1 = this.itime2 = time;  // don't lerp
114         }
115         else if ((this.iflags & IFLAG_VELOCITY) && vdist(this.ivelocity2 - this.ivelocity1, >, 1000))
116         {
117                 this.itime1 = this.itime2 = time;  // don't lerp
118         }
119         else if (dt >= 0.2)
120         {
121                 this.itime1 = this.itime2 = time;
122         }
123         else
124         {
125                 this.itime1 = serverprevtime;
126                 this.itime2 = time;
127         }
128 }
129
130 /** set origin based on iorigin1 (old pos), iorigin2 (desired pos), and time */
131 void InterpolateOrigin_Do(entity this)
132 {
133         if (this.itime1 && this.itime2 && this.itime1 != this.itime2)
134         {
135                 float f = bound(0, (time - this.itime1) / (this.itime2 - this.itime1), 1 + autocvar_cl_lerpexcess);
136                 float f_1 = 1 - f;
137                 if (this.iflags & IFLAG_ORIGIN) setorigin(this, f_1 * this.iorigin1 + f * this.iorigin2);
138                 if (this.iflags & IFLAG_ANGLES)
139                 {
140                         vector forward = f_1 * this.iforward1 + f * this.iforward2;
141                         vector up = f_1 * this.iup1 + f * this.iup2;
142                         this.angles = fixedvectoangles2(forward, up);
143                 }
144                 if (this.iflags & IFLAG_V_ANGLE)
145                 {
146                         vector forward = f_1 * this.ivforward1 + f * this.ivforward2;
147                         vector up = f_1 * this.ivup1 + f * this.ivup2;
148                         this.v_angle = fixedvectoangles2(forward, up);
149                 }
150                 else if (this.iflags & IFLAG_V_ANGLE_X)
151                 {
152                         this.v_angle_x = f_1 * this.ivforward1.x + f * this.ivforward2.x;
153                 }
154                 if (this.iflags & IFLAG_VELOCITY) this.velocity = f_1 * this.ivelocity1 + f * this.ivelocity2;
155         }
156 }
157
158 /** snap origin to iorigin2 (actual origin) */
159 void InterpolateOrigin_Undo(entity this)
160 {
161         if (this.iflags & IFLAG_ORIGIN) setorigin(this, this.iorigin2);
162         if (this.iflags & IFLAG_ANGLES) this.angles = fixedvectoangles2(this.iforward2, this.iup2);
163         if (this.iflags & IFLAG_V_ANGLE) this.v_angle = fixedvectoangles2(this.ivforward2, this.ivup2);
164         else if (this.iflags & IFLAG_V_ANGLE_X) this.v_angle_x = this.ivforward2_x;
165         if (this.iflags & IFLAG_VELOCITY) this.velocity = this.ivelocity2;
166 }