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(&sectors[i]), i));
57 			if (sectors[i].floordata)
58 				prev_floorheight.push_back(std::make_pair(P_FloorHeight(&sectors[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 = &sectors[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 = &sectors[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 = &sectors[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 = &sectors[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