Merge branch 'master' into martin-t/globals
[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                 FIXED_MAKE_VECTORS_NEW(this.angles, forward, right, up);
62                 if (f0 & IFLAG_VALID)
63                 {
64                         this.iforward1 = this.iforward2;
65                         this.iup1 = this.iup2;
66                 }
67                 else
68                 {
69                         this.iforward1 = forward;
70                         this.iup1 = up;
71                 }
72                 this.iforward2 = forward;
73                 this.iup2 = up;
74         }
75
76         if (this.iflags & IFLAG_V_ANGLE)
77         {
78                 FIXED_MAKE_VECTORS_NEW(this.v_angle, forward, right, up);
79                 if (f0 & IFLAG_VALID)
80                 {
81                         this.ivforward1 = this.ivforward2;
82                         this.ivup1 = this.ivup2;
83                 }
84                 else
85                 {
86                         this.ivforward1 = forward;
87                         this.ivup1 = up;
88                 }
89                 this.ivforward2 = forward;
90                 this.ivup2 = up;
91         }
92         else if (this.iflags & IFLAG_V_ANGLE_X)
93         {
94                 this.ivforward1_x = this.ivforward2_x;
95                 this.ivforward2_x = this.v_angle.x;
96         }
97
98         if (this.iflags & IFLAG_VELOCITY)
99         {
100                 this.ivelocity1 = this.ivelocity2;
101                 this.ivelocity2 = this.velocity;
102         }
103
104         if (this.iflags & IFLAG_TELEPORTED)
105         {
106                 this.iflags &= ~IFLAG_TELEPORTED;
107                 this.itime1 = this.itime2 = time;  // don't lerp
108         }
109         else if (vdist(this.iorigin2 - this.iorigin1, >, 1000))
110         {
111                 this.itime1 = this.itime2 = time;  // don't lerp
112         }
113         else if ((this.iflags & IFLAG_VELOCITY) && vdist(this.ivelocity2 - this.ivelocity1, >, 1000))
114         {
115                 this.itime1 = this.itime2 = time;  // don't lerp
116         }
117         else if (dt >= 0.2)
118         {
119                 this.itime1 = this.itime2 = time;
120         }
121         else
122         {
123                 this.itime1 = serverprevtime;
124                 this.itime2 = time;
125         }
126 }
127
128 /** set origin based on iorigin1 (old pos), iorigin2 (desired pos), and time */
129 void InterpolateOrigin_Do(entity this)
130 {
131         if (this.itime1 && this.itime2 && this.itime1 != this.itime2)
132         {
133                 float f = bound(0, (time - this.itime1) / (this.itime2 - this.itime1), 1 + autocvar_cl_lerpexcess);
134                 float f_1 = 1 - f;
135                 if (this.iflags & IFLAG_ORIGIN) setorigin(this, f_1 * this.iorigin1 + f * this.iorigin2);
136                 if (this.iflags & IFLAG_ANGLES)
137                 {
138                         vector forward = f_1 * this.iforward1 + f * this.iforward2;
139                         vector up = f_1 * this.iup1 + f * this.iup2;
140                         this.angles = fixedvectoangles2(forward, up);
141                 }
142                 if (this.iflags & IFLAG_V_ANGLE)
143                 {
144                         vector forward = f_1 * this.ivforward1 + f * this.ivforward2;
145                         vector up = f_1 * this.ivup1 + f * this.ivup2;
146                         this.v_angle = fixedvectoangles2(forward, up);
147                 }
148                 else if (this.iflags & IFLAG_V_ANGLE_X)
149                 {
150                         this.v_angle_x = f_1 * this.ivforward1.x + f * this.ivforward2.x;
151                 }
152                 if (this.iflags & IFLAG_VELOCITY) this.velocity = f_1 * this.ivelocity1 + f * this.ivelocity2;
153         }
154 }
155
156 /** snap origin to iorigin2 (actual origin) */
157 void InterpolateOrigin_Undo(entity this)
158 {
159         if (this.iflags & IFLAG_ORIGIN) setorigin(this, this.iorigin2);
160         if (this.iflags & IFLAG_ANGLES) this.angles = fixedvectoangles2(this.iforward2, this.iup2);
161         if (this.iflags & IFLAG_V_ANGLE) this.v_angle = fixedvectoangles2(this.ivforward2, this.ivup2);
162         else if (this.iflags & IFLAG_V_ANGLE_X) this.v_angle_x = this.ivforward2_x;
163         if (this.iflags & IFLAG_VELOCITY) this.velocity = this.ivelocity2;
164 }