diff options
Diffstat (limited to 'src/r_fps.c')
-rw-r--r-- | src/r_fps.c | 450 |
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 | |||
42 | int movement_smooth = false; | ||
43 | |||
44 | typedef 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 | |||
54 | typedef struct | ||
55 | { | ||
56 | interpolation_type_e type; | ||
57 | void *address; | ||
58 | } interpolation_t; | ||
59 | |||
60 | static int numinterpolations = 0; | ||
61 | |||
62 | tic_vars_t tic_vars; | ||
63 | |||
64 | view_vars_t original_view_vars; | ||
65 | |||
66 | extern int realtic_clock_rate; | ||
67 | void D_Display(void); | ||
68 | |||
69 | void R_InitInterpolation(void) | ||
70 | { | ||
71 | tic_vars.msec = realtic_clock_rate * TICRATE / 100000.0f; | ||
72 | } | ||
73 | |||
74 | typedef fixed_t fixed2_t[2]; | ||
75 | static fixed2_t *oldipos; | ||
76 | static fixed2_t *bakipos; | ||
77 | static interpolation_t *curipos; | ||
78 | |||
79 | static boolean NoInterpolateView; | ||
80 | static boolean didInterp; | ||
81 | boolean WasRenderedInTryRunTics; | ||
82 | |||
83 | void 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 | |||
112 | void R_ResetViewInterpolation () | ||
113 | { | ||
114 | NoInterpolateView = true; | ||
115 | } | ||
116 | |||
117 | static 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 | |||
146 | static 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 | |||
175 | static 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 | |||
223 | void 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 | |||
232 | int interpolations_max = 0; | ||
233 | |||
234 | static 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 | |||
258 | static 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 | |||
280 | void 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 | |||
298 | void 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 | |||
318 | void 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 | |||
335 | void 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 | |||
352 | static 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 | |||
412 | void 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 | |||
432 | void 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 | |||