r_fps.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451
  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. #include "doomstat.h"
  35. #include "r_defs.h"
  36. #include "r_state.h"
  37. #include "p_spec.h"
  38. #include "r_demo.h"
  39. #include "r_fps.h"
  40. int movement_smooth = false;
  41. typedef enum
  42. {
  43. INTERP_SectorFloor,
  44. INTERP_SectorCeiling,
  45. INTERP_Vertex,
  46. INTERP_WallPanning,
  47. INTERP_FloorPanning,
  48. INTERP_CeilingPanning
  49. } interpolation_type_e;
  50. typedef struct
  51. {
  52. interpolation_type_e type;
  53. void *address;
  54. } interpolation_t;
  55. static int numinterpolations = 0;
  56. tic_vars_t tic_vars;
  57. view_vars_t original_view_vars;
  58. extern int realtic_clock_rate;
  59. void D_Display(void);
  60. void R_InitInterpolation(void)
  61. {
  62. tic_vars.msec = realtic_clock_rate * TICRATE / 100000.0f;
  63. }
  64. typedef fixed_t fixed2_t[2];
  65. static fixed2_t *oldipos;
  66. static fixed2_t *bakipos;
  67. static interpolation_t *curipos;
  68. static boolean NoInterpolateView;
  69. static boolean didInterp;
  70. boolean WasRenderedInTryRunTics;
  71. void R_InterpolateView (player_t *player, fixed_t frac)
  72. {
  73. if (movement_smooth)
  74. {
  75. if (NoInterpolateView)
  76. {
  77. NoInterpolateView = false;
  78. original_view_vars.viewx = player->mo->x;
  79. original_view_vars.viewy = player->mo->y;
  80. original_view_vars.viewz = player->viewz;
  81. original_view_vars.viewangle = player->mo->angle + viewangleoffset;
  82. }
  83. viewx = original_view_vars.viewx + FixedMul (frac, player->mo->x - original_view_vars.viewx);
  84. viewy = original_view_vars.viewy + FixedMul (frac, player->mo->y - original_view_vars.viewy);
  85. viewz = original_view_vars.viewz + FixedMul (frac, player->viewz - original_view_vars.viewz);
  86. viewangle = original_view_vars.viewangle + FixedMul (frac, R_SmoothPlaying_Get(player->mo->angle) + viewangleoffset - original_view_vars.viewangle);
  87. }
  88. else
  89. {
  90. viewx = player->mo->x;
  91. viewy = player->mo->y;
  92. viewz = player->viewz;
  93. viewangle = R_SmoothPlaying_Get(player->mo->angle);
  94. }
  95. }
  96. void R_ResetViewInterpolation ()
  97. {
  98. NoInterpolateView = true;
  99. }
  100. static void R_CopyInterpToOld (int i)
  101. {
  102. switch (curipos[i].type)
  103. {
  104. case INTERP_SectorFloor:
  105. oldipos[i][0] = ((sector_t*)curipos[i].address)->floorheight;
  106. break;
  107. case INTERP_SectorCeiling:
  108. oldipos[i][0] = ((sector_t*)curipos[i].address)->ceilingheight;
  109. break;
  110. case INTERP_Vertex:
  111. oldipos[i][0] = ((vertex_t*)curipos[i].address)->x;
  112. oldipos[i][1] = ((vertex_t*)curipos[i].address)->y;
  113. break;
  114. case INTERP_WallPanning:
  115. oldipos[i][0] = ((side_t*)curipos[i].address)->rowoffset;
  116. oldipos[i][1] = ((side_t*)curipos[i].address)->textureoffset;
  117. break;
  118. case INTERP_FloorPanning:
  119. oldipos[i][0] = ((sector_t*)curipos[i].address)->floor_xoffs;
  120. oldipos[i][1] = ((sector_t*)curipos[i].address)->floor_yoffs;
  121. break;
  122. case INTERP_CeilingPanning:
  123. oldipos[i][0] = ((sector_t*)curipos[i].address)->ceiling_xoffs;
  124. oldipos[i][1] = ((sector_t*)curipos[i].address)->ceiling_yoffs;
  125. break;
  126. }
  127. }
  128. static void R_CopyBakToInterp (int i)
  129. {
  130. switch (curipos[i].type)
  131. {
  132. case INTERP_SectorFloor:
  133. ((sector_t*)curipos[i].address)->floorheight = bakipos[i][0];
  134. break;
  135. case INTERP_SectorCeiling:
  136. ((sector_t*)curipos[i].address)->ceilingheight = bakipos[i][0];
  137. break;
  138. case INTERP_Vertex:
  139. ((vertex_t*)curipos[i].address)->x = bakipos[i][0];
  140. ((vertex_t*)curipos[i].address)->y = bakipos[i][1];
  141. break;
  142. case INTERP_WallPanning:
  143. ((side_t*)curipos[i].address)->rowoffset = bakipos[i][0];
  144. ((side_t*)curipos[i].address)->textureoffset = bakipos[i][1];
  145. break;
  146. case INTERP_FloorPanning:
  147. ((sector_t*)curipos[i].address)->floor_xoffs = bakipos[i][0];
  148. ((sector_t*)curipos[i].address)->floor_yoffs = bakipos[i][1];
  149. break;
  150. case INTERP_CeilingPanning:
  151. ((sector_t*)curipos[i].address)->ceiling_xoffs = bakipos[i][0];
  152. ((sector_t*)curipos[i].address)->ceiling_yoffs = bakipos[i][1];
  153. break;
  154. }
  155. }
  156. static void R_DoAnInterpolation (int i, fixed_t smoothratio)
  157. {
  158. fixed_t pos;
  159. fixed_t *adr1 = NULL;
  160. fixed_t *adr2 = NULL;
  161. switch (curipos[i].type)
  162. {
  163. case INTERP_SectorFloor:
  164. adr1 = &((sector_t*)curipos[i].address)->floorheight;
  165. break;
  166. case INTERP_SectorCeiling:
  167. adr1 = &((sector_t*)curipos[i].address)->ceilingheight;
  168. break;
  169. case INTERP_Vertex:
  170. adr1 = &((vertex_t*)curipos[i].address)->x;
  171. //// adr2 = &((vertex_t*)curipos[i].Address)->y;
  172. break;
  173. case INTERP_WallPanning:
  174. adr1 = &((side_t*)curipos[i].address)->rowoffset;
  175. adr2 = &((side_t*)curipos[i].address)->textureoffset;
  176. break;
  177. case INTERP_FloorPanning:
  178. adr1 = &((sector_t*)curipos[i].address)->floor_xoffs;
  179. adr2 = &((sector_t*)curipos[i].address)->floor_yoffs;
  180. break;
  181. case INTERP_CeilingPanning:
  182. adr1 = &((sector_t*)curipos[i].address)->ceiling_xoffs;
  183. adr2 = &((sector_t*)curipos[i].address)->ceiling_yoffs;
  184. break;
  185. default:
  186. return;
  187. }
  188. if (adr1)
  189. {
  190. pos = bakipos[i][0] = *adr1;
  191. *adr1 = oldipos[i][0] + FixedMul (pos - oldipos[i][0], smoothratio);
  192. }
  193. if (adr2)
  194. {
  195. pos = bakipos[i][1] = *adr2;
  196. *adr2 = oldipos[i][1] + FixedMul (pos - oldipos[i][1], smoothratio);
  197. }
  198. }
  199. void R_UpdateInterpolations()
  200. {
  201. int i;
  202. if (!movement_smooth)
  203. return;
  204. for (i = numinterpolations-1; i >= 0; --i)
  205. R_CopyInterpToOld (i);
  206. }
  207. int interpolations_max = 0;
  208. static void R_SetInterpolation(interpolation_type_e type, void *posptr)
  209. {
  210. int i;
  211. if (!movement_smooth)
  212. return;
  213. if (numinterpolations >= interpolations_max) {
  214. interpolations_max = interpolations_max ? interpolations_max * 2 : 256;
  215. oldipos = (fixed2_t*)realloc(oldipos, sizeof(*oldipos) * interpolations_max);
  216. bakipos = (fixed2_t*)realloc(bakipos, sizeof(*bakipos) * interpolations_max);
  217. curipos = (interpolation_t*)realloc(curipos, sizeof(*curipos) * interpolations_max);
  218. }
  219. for(i = numinterpolations-1; i >= 0; i--)
  220. if (curipos[i].address == posptr && curipos[i].type == type)
  221. return;
  222. curipos[numinterpolations].address = posptr;
  223. curipos[numinterpolations].type = type;
  224. R_CopyInterpToOld (numinterpolations);
  225. numinterpolations++;
  226. }
  227. static void R_StopInterpolation(interpolation_type_e type, void *posptr)
  228. {
  229. int i;
  230. if (!movement_smooth)
  231. return;
  232. for(i=numinterpolations-1; i>= 0; --i)
  233. {
  234. if (curipos[i].address == posptr && curipos[i].type == type)
  235. {
  236. numinterpolations--;
  237. oldipos[i][0] = oldipos[numinterpolations][0];
  238. oldipos[i][1] = oldipos[numinterpolations][1];
  239. bakipos[i][0] = bakipos[numinterpolations][0];
  240. bakipos[i][1] = bakipos[numinterpolations][1];
  241. curipos[i] = curipos[numinterpolations];
  242. break;
  243. }
  244. }
  245. }
  246. void R_StopAllInterpolations(void)
  247. {
  248. int i;
  249. if (!movement_smooth)
  250. return;
  251. for(i=numinterpolations-1; i>= 0; --i)
  252. {
  253. numinterpolations--;
  254. oldipos[i][0] = oldipos[numinterpolations][0];
  255. oldipos[i][1] = oldipos[numinterpolations][1];
  256. bakipos[i][0] = bakipos[numinterpolations][0];
  257. bakipos[i][1] = bakipos[numinterpolations][1];
  258. curipos[i] = curipos[numinterpolations];
  259. }
  260. }
  261. void R_DoInterpolations(fixed_t smoothratio)
  262. {
  263. int i;
  264. if (!movement_smooth)
  265. return;
  266. if (smoothratio == FRACUNIT)
  267. {
  268. didInterp = false;
  269. return;
  270. }
  271. didInterp = true;
  272. for (i = numinterpolations-1; i >= 0; --i)
  273. {
  274. R_DoAnInterpolation (i, smoothratio);
  275. }
  276. }
  277. void R_RestoreInterpolations()
  278. {
  279. int i;
  280. if (!movement_smooth)
  281. return;
  282. if (didInterp)
  283. {
  284. didInterp = false;
  285. for (i = numinterpolations-1; i >= 0; --i)
  286. {
  287. R_CopyBakToInterp (i);
  288. }
  289. }
  290. }
  291. void R_ActivateSectorInterpolations()
  292. {
  293. int i;
  294. sector_t *sec;
  295. if (!movement_smooth)
  296. return;
  297. for (i=0, sec = sectors ; i<numsectors ; i++,sec++)
  298. {
  299. if (sec->floordata)
  300. R_SetInterpolation (INTERP_SectorFloor, sec);
  301. if (sec->ceilingdata)
  302. R_SetInterpolation (INTERP_SectorCeiling, sec);
  303. }
  304. }
  305. static void R_InterpolationGetData(thinker_t *th,
  306. interpolation_type_e *type1, interpolation_type_e *type2,
  307. void **posptr1, void **posptr2)
  308. {
  309. *posptr1 = NULL;
  310. *posptr2 = NULL;
  311. if (th->function == T_MoveFloor)
  312. {
  313. *type1 = INTERP_SectorFloor;
  314. *posptr1 = ((floormove_t *)th)->sector;
  315. }
  316. else
  317. if (th->function == T_PlatRaise)
  318. {
  319. *type1 = INTERP_SectorFloor;
  320. *posptr1 = ((plat_t *)th)->sector;
  321. }
  322. else
  323. if (th->function == T_MoveCeiling)
  324. {
  325. *type1 = INTERP_SectorCeiling;
  326. *posptr1 = ((ceiling_t *)th)->sector;
  327. }
  328. else
  329. if (th->function == T_VerticalDoor)
  330. {
  331. *type1 = INTERP_SectorCeiling;
  332. *posptr1 = ((vldoor_t *)th)->sector;
  333. }
  334. else
  335. if (th->function == T_MoveElevator)
  336. {
  337. *type1 = INTERP_SectorFloor;
  338. *posptr1 = ((elevator_t *)th)->sector;
  339. *type2 = INTERP_SectorCeiling;
  340. *posptr2 = ((elevator_t *)th)->sector;
  341. }
  342. else
  343. if (th->function == T_Scroll)
  344. {
  345. switch (((scroll_t *)th)->type)
  346. {
  347. case sc_side:
  348. *type1 = INTERP_WallPanning;
  349. *posptr1 = sides + ((scroll_t *)th)->affectee;
  350. break;
  351. case sc_floor:
  352. *type1 = INTERP_FloorPanning;
  353. *posptr1 = sectors + ((scroll_t *)th)->affectee;
  354. break;
  355. case sc_ceiling:
  356. *type1 = INTERP_CeilingPanning;
  357. *posptr1 = sectors + ((scroll_t *)th)->affectee;
  358. break;
  359. default: ;
  360. }
  361. }
  362. }
  363. void R_ActivateThinkerInterpolations(thinker_t *th)
  364. {
  365. void *posptr1;
  366. void *posptr2;
  367. interpolation_type_e type1, type2;
  368. if (!movement_smooth)
  369. return;
  370. R_InterpolationGetData(th, &type1, &type2, &posptr1, &posptr2);
  371. if(posptr1)
  372. {
  373. R_SetInterpolation (type1, posptr1);
  374. if(posptr2)
  375. R_SetInterpolation (type2, posptr2);
  376. }
  377. }
  378. void R_StopInterpolationIfNeeded(thinker_t *th)
  379. {
  380. void *posptr1;
  381. void *posptr2;
  382. interpolation_type_e type1, type2;
  383. if (!movement_smooth)
  384. return;
  385. R_InterpolationGetData(th, &type1, &type2, &posptr1, &posptr2);
  386. if(posptr1)
  387. {
  388. R_StopInterpolation (type1, posptr1);
  389. if(posptr2)
  390. R_StopInterpolation (type2, posptr2);
  391. }
  392. }