1 // Emacs style mode select -*- C++ -*-
2 //-----------------------------------------------------------------------------
3 //
4 // $Id: r_interp.cpp 3798 2013-04-24 03:09:33Z dr_sean $
5 //
6 // Copyright (C) 1993-1996 by id Software, Inc.
7 // Copyright (C) 2006-2014 by The Odamex Team.
8 //
9 // This program is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU General Public License
11 // as published by the Free Software Foundation; either version 2
12 // of the License, or (at your option) any later version.
13 //
14 // This program is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 // GNU General Public License for more details.
18 //
19 // DESCRIPTION:
20 // Interpolation of moving ceiling/floor planes, scrolling texture, etc
21 // for uncapped framerates.
22 //
23 //-----------------------------------------------------------------------------
24
25 #include "doomstat.h"
26 #include "m_fixed.h"
27 #include "r_state.h"
28 #include "p_local.h"
29
30 #include <vector>
31
32 typedef std::pair<fixed_t, unsigned int> fixed_uint_pair;
33
34 static std::vector<fixed_uint_pair> prev_ceilingheight;
35 static std::vector<fixed_uint_pair> saved_ceilingheight;
36 static std::vector<fixed_uint_pair> prev_floorheight;
37 static std::vector<fixed_uint_pair> saved_floorheight;
38
39 //
40 // R_InterpolationTicker
41 //
42 // Records the current height of all moving planes and position of scrolling
43 // textures, which will be used as the previous position during iterpolation.
44 // This should be called once per gametic.
45 //
R_InterpolationTicker()46 void R_InterpolationTicker()
47 {
48 prev_ceilingheight.clear();
49 prev_floorheight.clear();
50
51 if (gamestate == GS_LEVEL)
52 {
53 for (int i = 0; i < numsectors; i++)
54 {
55 if (sectors[i].ceilingdata)
56 prev_ceilingheight.push_back(std::make_pair(P_CeilingHeight(§ors[i]), i));
57 if (sectors[i].floordata)
58 prev_floorheight.push_back(std::make_pair(P_FloorHeight(§ors[i]), i));
59 }
60 }
61 }
62
63
64 //
65 // R_ResetInterpolation
66 //
67 // Clears any saved interpolation related data. This should be called whenever
68 // a map is loaded.
69 //
R_ResetInterpolation()70 void R_ResetInterpolation()
71 {
72 prev_ceilingheight.clear();
73 prev_floorheight.clear();
74 saved_ceilingheight.clear();
75 saved_floorheight.clear();
76 }
77
78
79 //
80 // R_BeginInterpolation
81 //
82 // Saves the current height of all moving planes and position of scrolling
83 // textures, which will be restored by R_EndInterpolation. The height of a
84 // moving plane will be interpolated between the previous height and this
85 // current height. This should be called every time a frame is rendered.
86 //
R_BeginInterpolation(fixed_t amount)87 void R_BeginInterpolation(fixed_t amount)
88 {
89 saved_ceilingheight.clear();
90 saved_floorheight.clear();
91
92 if (gamestate == GS_LEVEL)
93 {
94 for (std::vector<fixed_uint_pair>::const_iterator ceiling_it = prev_ceilingheight.begin();
95 ceiling_it != prev_ceilingheight.end(); ++ceiling_it)
96 {
97 unsigned int secnum = ceiling_it->second;
98 sector_t* sector = §ors[secnum];
99
100 fixed_t old_value = ceiling_it->first;
101 fixed_t cur_value = P_CeilingHeight(sector);
102
103 saved_ceilingheight.push_back(std::make_pair(cur_value, secnum));
104
105 fixed_t new_value = old_value + FixedMul(cur_value - old_value, amount);
106 P_SetCeilingHeight(sector, new_value);
107 }
108
109 for (std::vector<fixed_uint_pair>::const_iterator floor_it = prev_floorheight.begin();
110 floor_it != prev_floorheight.end(); ++floor_it)
111 {
112 unsigned int secnum = floor_it->second;
113 sector_t* sector = §ors[secnum];
114
115 fixed_t old_value = floor_it->first;
116 fixed_t cur_value = P_FloorHeight(sector);
117
118 saved_floorheight.push_back(std::make_pair(cur_value, secnum));
119
120 fixed_t new_value = old_value + FixedMul(cur_value - old_value, amount);
121 P_SetFloorHeight(sector, new_value);
122 }
123 }
124 }
125
126 //
127 // R_EndInterpolation
128 //
129 // Restores the saved height of all moving planes and position of scrolling
130 // textures. This should be called at the end of every frame rendered.
131 //
R_EndInterpolation()132 void R_EndInterpolation()
133 {
134 if (gamestate == GS_LEVEL)
135 {
136 for (std::vector<fixed_uint_pair>::const_iterator ceiling_it = saved_ceilingheight.begin();
137 ceiling_it != saved_ceilingheight.end(); ++ceiling_it)
138 {
139 sector_t* sector = §ors[ceiling_it->second];
140 P_SetCeilingHeight(sector, ceiling_it->first);
141 }
142
143 for (std::vector<fixed_uint_pair>::const_iterator floor_it = saved_floorheight.begin();
144 floor_it != saved_floorheight.end(); ++floor_it)
145 {
146 sector_t* sector = §ors[floor_it->second];
147 P_SetFloorHeight(sector, floor_it->first);
148 }
149 }
150 }
151
152 //
153 // R_InterpolateCamera
154 //
155 // Interpolate between the current position and the previous position
156 // of the camera. If not using uncapped framerate / interpolation,
157 // render_lerp_amount will be FRACUNIT.
158 //
R_InterpolateCamera(fixed_t amount)159 void R_InterpolateCamera(fixed_t amount)
160 {
161 if (gamestate == GS_LEVEL && camera)
162 {
163 // interpolate amount/FRACUNIT percent between previous value and current value
164 viewangle = viewangleoffset + camera->prevangle +
165 FixedMul(amount, camera->angle - camera->prevangle);
166 viewx = camera->prevx + FixedMul(amount, camera->x - camera->prevx);
167 viewy = camera->prevy + FixedMul(amount, camera->y - camera->prevy);
168 if (camera->player)
169 viewz = camera->player->prevviewz +
170 FixedMul(amount, camera->player->viewz - camera->player->prevviewz);
171 else
172 viewz = camera->prevz +
173 FixedMul(amount, camera->z - camera->prevz);
174 }
175 }
176
177 VERSION_CONTROL (r_interp_cpp, "$Id: r_interp.cpp 3798 2013-04-24 03:09:33Z dr_sean $")
178
179