aboutsummaryrefslogtreecommitdiff
path: root/src/r_fps.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/r_fps.c')
-rw-r--r--src/r_fps.c450
1 files changed, 450 insertions, 0 deletions
diff --git a/src/r_fps.c b/src/r_fps.c
new file mode 100644
index 0000000..09b7bc0
--- /dev/null
+++ b/src/r_fps.c
@@ -0,0 +1,450 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom: a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze, Andrey Budko
11 * Copyright 2005, 2006 by
12 * Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
27 * 02111-1307, USA.
28 *
29 * DESCRIPTION:
30 * Uncapped framerate stuff
31 *
32 *---------------------------------------------------------------------
33 */
34
35#include "doomstat.h"
36#include "r_defs.h"
37#include "r_state.h"
38#include "p_spec.h"
39#include "r_demo.h"
40#include "r_fps.h"
41
42int movement_smooth = false;
43
44typedef enum
45{
46 INTERP_SectorFloor,
47 INTERP_SectorCeiling,
48 INTERP_Vertex,
49 INTERP_WallPanning,
50 INTERP_FloorPanning,
51 INTERP_CeilingPanning
52} interpolation_type_e;
53
54typedef struct
55{
56 interpolation_type_e type;
57 void *address;
58} interpolation_t;
59
60static int numinterpolations = 0;
61
62tic_vars_t tic_vars;
63
64view_vars_t original_view_vars;
65
66extern int realtic_clock_rate;
67void D_Display(void);
68
69void R_InitInterpolation(void)
70{
71 tic_vars.msec = realtic_clock_rate * TICRATE / 100000.0f;
72}
73
74typedef fixed_t fixed2_t[2];
75static fixed2_t *oldipos;
76static fixed2_t *bakipos;
77static interpolation_t *curipos;
78
79static boolean NoInterpolateView;
80static boolean didInterp;
81boolean WasRenderedInTryRunTics;
82
83void R_InterpolateView (player_t *player, fixed_t frac)
84{
85 if (movement_smooth)
86 {
87 if (NoInterpolateView)
88 {
89 NoInterpolateView = false;
90 original_view_vars.viewx = player->mo->x;
91 original_view_vars.viewy = player->mo->y;
92 original_view_vars.viewz = player->viewz;
93
94 original_view_vars.viewangle = player->mo->angle + viewangleoffset;
95 }
96
97 viewx = original_view_vars.viewx + FixedMul (frac, player->mo->x - original_view_vars.viewx);
98 viewy = original_view_vars.viewy + FixedMul (frac, player->mo->y - original_view_vars.viewy);
99 viewz = original_view_vars.viewz + FixedMul (frac, player->viewz - original_view_vars.viewz);
100
101 viewangle = original_view_vars.viewangle + FixedMul (frac, R_SmoothPlaying_Get(player->mo->angle) + viewangleoffset - original_view_vars.viewangle);
102 }
103 else
104 {
105 viewx = player->mo->x;
106 viewy = player->mo->y;
107 viewz = player->viewz;
108 viewangle = R_SmoothPlaying_Get(player->mo->angle);
109 }
110}
111
112void R_ResetViewInterpolation ()
113{
114 NoInterpolateView = true;
115}
116
117static void R_CopyInterpToOld (int i)
118{
119 switch (curipos[i].type)
120 {
121 case INTERP_SectorFloor:
122 oldipos[i][0] = ((sector_t*)curipos[i].address)->floorheight;
123 break;
124 case INTERP_SectorCeiling:
125 oldipos[i][0] = ((sector_t*)curipos[i].address)->ceilingheight;
126 break;
127 case INTERP_Vertex:
128 oldipos[i][0] = ((vertex_t*)curipos[i].address)->x;
129 oldipos[i][1] = ((vertex_t*)curipos[i].address)->y;
130 break;
131 case INTERP_WallPanning:
132 oldipos[i][0] = ((side_t*)curipos[i].address)->rowoffset;
133 oldipos[i][1] = ((side_t*)curipos[i].address)->textureoffset;
134 break;
135 case INTERP_FloorPanning:
136 oldipos[i][0] = ((sector_t*)curipos[i].address)->floor_xoffs;
137 oldipos[i][1] = ((sector_t*)curipos[i].address)->floor_yoffs;
138 break;
139 case INTERP_CeilingPanning:
140 oldipos[i][0] = ((sector_t*)curipos[i].address)->ceiling_xoffs;
141 oldipos[i][1] = ((sector_t*)curipos[i].address)->ceiling_yoffs;
142 break;
143 }
144}
145
146static void R_CopyBakToInterp (int i)
147{
148 switch (curipos[i].type)
149 {
150 case INTERP_SectorFloor:
151 ((sector_t*)curipos[i].address)->floorheight = bakipos[i][0];
152 break;
153 case INTERP_SectorCeiling:
154 ((sector_t*)curipos[i].address)->ceilingheight = bakipos[i][0];
155 break;
156 case INTERP_Vertex:
157 ((vertex_t*)curipos[i].address)->x = bakipos[i][0];
158 ((vertex_t*)curipos[i].address)->y = bakipos[i][1];
159 break;
160 case INTERP_WallPanning:
161 ((side_t*)curipos[i].address)->rowoffset = bakipos[i][0];
162 ((side_t*)curipos[i].address)->textureoffset = bakipos[i][1];
163 break;
164 case INTERP_FloorPanning:
165 ((sector_t*)curipos[i].address)->floor_xoffs = bakipos[i][0];
166 ((sector_t*)curipos[i].address)->floor_yoffs = bakipos[i][1];
167 break;
168 case INTERP_CeilingPanning:
169 ((sector_t*)curipos[i].address)->ceiling_xoffs = bakipos[i][0];
170 ((sector_t*)curipos[i].address)->ceiling_yoffs = bakipos[i][1];
171 break;
172 }
173}
174
175static void R_DoAnInterpolation (int i, fixed_t smoothratio)
176{
177 fixed_t pos;
178 fixed_t *adr1 = NULL;
179 fixed_t *adr2 = NULL;
180
181 switch (curipos[i].type)
182 {
183 case INTERP_SectorFloor:
184 adr1 = &((sector_t*)curipos[i].address)->floorheight;
185 break;
186 case INTERP_SectorCeiling:
187 adr1 = &((sector_t*)curipos[i].address)->ceilingheight;
188 break;
189 case INTERP_Vertex:
190 adr1 = &((vertex_t*)curipos[i].address)->x;
191//// adr2 = &((vertex_t*)curipos[i].Address)->y;
192 break;
193 case INTERP_WallPanning:
194 adr1 = &((side_t*)curipos[i].address)->rowoffset;
195 adr2 = &((side_t*)curipos[i].address)->textureoffset;
196 break;
197 case INTERP_FloorPanning:
198 adr1 = &((sector_t*)curipos[i].address)->floor_xoffs;
199 adr2 = &((sector_t*)curipos[i].address)->floor_yoffs;
200 break;
201 case INTERP_CeilingPanning:
202 adr1 = &((sector_t*)curipos[i].address)->ceiling_xoffs;
203 adr2 = &((sector_t*)curipos[i].address)->ceiling_yoffs;
204 break;
205
206 default:
207 return;
208 }
209
210 if (adr1)
211 {
212 pos = bakipos[i][0] = *adr1;
213 *adr1 = oldipos[i][0] + FixedMul (pos - oldipos[i][0], smoothratio);
214 }
215
216 if (adr2)
217 {
218 pos = bakipos[i][1] = *adr2;
219 *adr2 = oldipos[i][1] + FixedMul (pos - oldipos[i][1], smoothratio);
220 }
221}
222
223void R_UpdateInterpolations()
224{
225 int i;
226 if (!movement_smooth)
227 return;
228 for (i = numinterpolations-1; i >= 0; --i)
229 R_CopyInterpToOld (i);
230}
231
232int interpolations_max = 0;
233
234static void R_SetInterpolation(interpolation_type_e type, void *posptr)
235{
236 int i;
237 if (!movement_smooth)
238 return;
239
240 if (numinterpolations >= interpolations_max) {
241 interpolations_max = interpolations_max ? interpolations_max * 2 : 256;
242
243 oldipos = (fixed2_t*)realloc(oldipos, sizeof(*oldipos) * interpolations_max);
244 bakipos = (fixed2_t*)realloc(bakipos, sizeof(*bakipos) * interpolations_max);
245 curipos = (interpolation_t*)realloc(curipos, sizeof(*curipos) * interpolations_max);
246 }
247
248 for(i = numinterpolations-1; i >= 0; i--)
249 if (curipos[i].address == posptr && curipos[i].type == type)
250 return;
251
252 curipos[numinterpolations].address = posptr;
253 curipos[numinterpolations].type = type;
254 R_CopyInterpToOld (numinterpolations);
255 numinterpolations++;
256}
257
258static void R_StopInterpolation(interpolation_type_e type, void *posptr)
259{
260 int i;
261
262 if (!movement_smooth)
263 return;
264
265 for(i=numinterpolations-1; i>= 0; --i)
266 {
267 if (curipos[i].address == posptr && curipos[i].type == type)
268 {
269 numinterpolations--;
270 oldipos[i][0] = oldipos[numinterpolations][0];
271 oldipos[i][1] = oldipos[numinterpolations][1];
272 bakipos[i][0] = bakipos[numinterpolations][0];
273 bakipos[i][1] = bakipos[numinterpolations][1];
274 curipos[i] = curipos[numinterpolations];
275 break;
276 }
277 }
278}
279
280void R_StopAllInterpolations(void)
281{
282 int i;
283
284 if (!movement_smooth)
285 return;
286
287 for(i=numinterpolations-1; i>= 0; --i)
288 {
289 numinterpolations--;
290 oldipos[i][0] = oldipos[numinterpolations][0];
291 oldipos[i][1] = oldipos[numinterpolations][1];
292 bakipos[i][0] = bakipos[numinterpolations][0];
293 bakipos[i][1] = bakipos[numinterpolations][1];
294 curipos[i] = curipos[numinterpolations];
295 }
296}
297
298void R_DoInterpolations(fixed_t smoothratio)
299{
300 int i;
301 if (!movement_smooth)
302 return;
303
304 if (smoothratio == FRACUNIT)
305 {
306 didInterp = false;
307 return;
308 }
309
310 didInterp = true;
311
312 for (i = numinterpolations-1; i >= 0; --i)
313 {
314 R_DoAnInterpolation (i, smoothratio);
315 }
316}
317
318void R_RestoreInterpolations()
319{
320 int i;
321
322 if (!movement_smooth)
323 return;
324
325 if (didInterp)
326 {
327 didInterp = false;
328 for (i = numinterpolations-1; i >= 0; --i)
329 {
330 R_CopyBakToInterp (i);
331 }
332 }
333}
334
335void R_ActivateSectorInterpolations()
336{
337 int i;
338 sector_t *sec;
339
340 if (!movement_smooth)
341 return;
342
343 for (i=0, sec = sectors ; i<numsectors ; i++,sec++)
344 {
345 if (sec->floordata)
346 R_SetInterpolation (INTERP_SectorFloor, sec);
347 if (sec->ceilingdata)
348 R_SetInterpolation (INTERP_SectorCeiling, sec);
349 }
350}
351
352static void R_InterpolationGetData(thinker_t *th,
353 interpolation_type_e *type1, interpolation_type_e *type2,
354 void **posptr1, void **posptr2)
355{
356 *posptr1 = NULL;
357 *posptr2 = NULL;
358
359 if (th->function == T_MoveFloor)
360 {
361 *type1 = INTERP_SectorFloor;
362 *posptr1 = ((floormove_t *)th)->sector;
363 }
364 else
365 if (th->function == T_PlatRaise)
366 {
367 *type1 = INTERP_SectorFloor;
368 *posptr1 = ((plat_t *)th)->sector;
369 }
370 else
371 if (th->function == T_MoveCeiling)
372 {
373 *type1 = INTERP_SectorCeiling;
374 *posptr1 = ((ceiling_t *)th)->sector;
375 }
376 else
377 if (th->function == T_VerticalDoor)
378 {
379 *type1 = INTERP_SectorCeiling;
380 *posptr1 = ((vldoor_t *)th)->sector;
381 }
382 else
383 if (th->function == T_MoveElevator)
384 {
385 *type1 = INTERP_SectorFloor;
386 *posptr1 = ((elevator_t *)th)->sector;
387 *type2 = INTERP_SectorCeiling;
388 *posptr2 = ((elevator_t *)th)->sector;
389 }
390 else
391 if (th->function == T_Scroll)
392 {
393 switch (((scroll_t *)th)->type)
394 {
395 case sc_side:
396 *type1 = INTERP_WallPanning;
397 *posptr1 = sides + ((scroll_t *)th)->affectee;
398 break;
399 case sc_floor:
400 *type1 = INTERP_FloorPanning;
401 *posptr1 = sectors + ((scroll_t *)th)->affectee;
402 break;
403 case sc_ceiling:
404 *type1 = INTERP_CeilingPanning;
405 *posptr1 = sectors + ((scroll_t *)th)->affectee;
406 break;
407 default: ;
408 }
409 }
410}
411
412void R_ActivateThinkerInterpolations(thinker_t *th)
413{
414 void *posptr1;
415 void *posptr2;
416 interpolation_type_e type1, type2;
417
418 if (!movement_smooth)
419 return;
420
421 R_InterpolationGetData(th, &type1, &type2, &posptr1, &posptr2);
422
423 if(posptr1)
424 {
425 R_SetInterpolation (type1, posptr1);
426
427 if(posptr2)
428 R_SetInterpolation (type2, posptr2);
429 }
430}
431
432void R_StopInterpolationIfNeeded(thinker_t *th)
433{
434 void *posptr1;
435 void *posptr2;
436 interpolation_type_e type1, type2;
437
438 if (!movement_smooth)
439 return;
440
441 R_InterpolationGetData(th, &type1, &type2, &posptr1, &posptr2);
442
443 if(posptr1)
444 {
445 R_StopInterpolation (type1, posptr1);
446 if(posptr2)
447 R_StopInterpolation (type2, posptr2);
448 }
449}
450