dvr/app/jni/prboom/r_fps.c
2016-03-03 22:28:59 +00:00

473 lines
12 KiB
C

/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom: a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze, Andrey Budko
* Copyright 2005, 2006 by
* Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* Uncapped framerate stuff
*
*---------------------------------------------------------------------
*/
#include "doomstat.h"
#include "r_defs.h"
#include "r_state.h"
#include "p_spec.h"
#include "r_demo.h"
#include "r_fps.h"
int movement_smooth = false;
typedef enum
{
INTERP_SectorFloor,
INTERP_SectorCeiling,
INTERP_Vertex,
INTERP_WallPanning,
INTERP_FloorPanning,
INTERP_CeilingPanning
} interpolation_type_e;
typedef struct
{
interpolation_type_e type;
void *address;
} interpolation_t;
static int numinterpolations = 0;
tic_vars_t tic_vars;
view_vars_t original_view_vars;
fixed_t r_stereo_offset = 0x40000;
extern int realtic_clock_rate;
void D_Display(void);
void R_InitInterpolation(void)
{
tic_vars.msec = realtic_clock_rate * TICRATE / 100000.0f;
}
typedef fixed_t fixed2_t[2];
static fixed2_t *oldipos;
static fixed2_t *bakipos;
static interpolation_t *curipos;
static boolean NoInterpolateView;
static boolean didInterp;
boolean WasRenderedInTryRunTics;
extern float hmdRoll;
void R_StereoOffset(fixed_t *viewx, fixed_t *viewy, angle_t angle, fixed_t move)
{
angle >>= ANGLETOFINESHIFT;
*viewx += FixedMul(move,finecosine[angle]);
*viewy += FixedMul(move,finesine[angle]);
}
void R_InterpolateView (player_t *player, fixed_t frac, int eye)
{
if (movement_smooth)
{
if (NoInterpolateView)
{
NoInterpolateView = false;
original_view_vars.viewx = player->mo->x;
original_view_vars.viewy = player->mo->y;
original_view_vars.viewz = player->viewz;
original_view_vars.viewangle = player->mo->angle + viewangleoffset;
}
viewx = original_view_vars.viewx + FixedMul (frac, player->mo->x - original_view_vars.viewx);
viewy = original_view_vars.viewy + FixedMul (frac, player->mo->y - original_view_vars.viewy);
viewz = original_view_vars.viewz + FixedMul (frac, player->viewz - original_view_vars.viewz);
viewangle = original_view_vars.viewangle + FixedMul (frac, R_SmoothPlaying_Get(player->mo->angle) + viewangleoffset - original_view_vars.viewangle);
}
else
{
viewx = player->mo->x;
viewy = player->mo->y;
viewz = player->viewz;
viewangle = R_SmoothPlaying_Get(player->mo->angle);
}
//More we roll, less we stereo
float mult = 1.0f;
mult -= fabs(hmdRoll)/22.5f;
if (mult < 0.0f)
mult = 0.0f;
//Apply stereo offset
if (eye == 1)
R_StereoOffset(&viewx, &viewy, viewangle-ANG90, r_stereo_offset * mult);
else
R_StereoOffset(&viewx, &viewy, viewangle+ANG90, r_stereo_offset * mult);
}
void R_ResetViewInterpolation ()
{
NoInterpolateView = true;
}
static void R_CopyInterpToOld (int i)
{
switch (curipos[i].type)
{
case INTERP_SectorFloor:
oldipos[i][0] = ((sector_t*)curipos[i].address)->floorheight;
break;
case INTERP_SectorCeiling:
oldipos[i][0] = ((sector_t*)curipos[i].address)->ceilingheight;
break;
case INTERP_Vertex:
oldipos[i][0] = ((vertex_t*)curipos[i].address)->x;
oldipos[i][1] = ((vertex_t*)curipos[i].address)->y;
break;
case INTERP_WallPanning:
oldipos[i][0] = ((side_t*)curipos[i].address)->rowoffset;
oldipos[i][1] = ((side_t*)curipos[i].address)->textureoffset;
break;
case INTERP_FloorPanning:
oldipos[i][0] = ((sector_t*)curipos[i].address)->floor_xoffs;
oldipos[i][1] = ((sector_t*)curipos[i].address)->floor_yoffs;
break;
case INTERP_CeilingPanning:
oldipos[i][0] = ((sector_t*)curipos[i].address)->ceiling_xoffs;
oldipos[i][1] = ((sector_t*)curipos[i].address)->ceiling_yoffs;
break;
}
}
static void R_CopyBakToInterp (int i)
{
switch (curipos[i].type)
{
case INTERP_SectorFloor:
((sector_t*)curipos[i].address)->floorheight = bakipos[i][0];
break;
case INTERP_SectorCeiling:
((sector_t*)curipos[i].address)->ceilingheight = bakipos[i][0];
break;
case INTERP_Vertex:
((vertex_t*)curipos[i].address)->x = bakipos[i][0];
((vertex_t*)curipos[i].address)->y = bakipos[i][1];
break;
case INTERP_WallPanning:
((side_t*)curipos[i].address)->rowoffset = bakipos[i][0];
((side_t*)curipos[i].address)->textureoffset = bakipos[i][1];
break;
case INTERP_FloorPanning:
((sector_t*)curipos[i].address)->floor_xoffs = bakipos[i][0];
((sector_t*)curipos[i].address)->floor_yoffs = bakipos[i][1];
break;
case INTERP_CeilingPanning:
((sector_t*)curipos[i].address)->ceiling_xoffs = bakipos[i][0];
((sector_t*)curipos[i].address)->ceiling_yoffs = bakipos[i][1];
break;
}
}
static void R_DoAnInterpolation (int i, fixed_t smoothratio)
{
fixed_t pos;
fixed_t *adr1 = NULL;
fixed_t *adr2 = NULL;
switch (curipos[i].type)
{
case INTERP_SectorFloor:
adr1 = &((sector_t*)curipos[i].address)->floorheight;
break;
case INTERP_SectorCeiling:
adr1 = &((sector_t*)curipos[i].address)->ceilingheight;
break;
case INTERP_Vertex:
adr1 = &((vertex_t*)curipos[i].address)->x;
//// adr2 = &((vertex_t*)curipos[i].Address)->y;
break;
case INTERP_WallPanning:
adr1 = &((side_t*)curipos[i].address)->rowoffset;
adr2 = &((side_t*)curipos[i].address)->textureoffset;
break;
case INTERP_FloorPanning:
adr1 = &((sector_t*)curipos[i].address)->floor_xoffs;
adr2 = &((sector_t*)curipos[i].address)->floor_yoffs;
break;
case INTERP_CeilingPanning:
adr1 = &((sector_t*)curipos[i].address)->ceiling_xoffs;
adr2 = &((sector_t*)curipos[i].address)->ceiling_yoffs;
break;
default:
return;
}
if (adr1)
{
pos = bakipos[i][0] = *adr1;
*adr1 = oldipos[i][0] + FixedMul (pos - oldipos[i][0], smoothratio);
}
if (adr2)
{
pos = bakipos[i][1] = *adr2;
*adr2 = oldipos[i][1] + FixedMul (pos - oldipos[i][1], smoothratio);
}
}
void R_UpdateInterpolations()
{
int i;
if (!movement_smooth)
return;
for (i = numinterpolations-1; i >= 0; --i)
R_CopyInterpToOld (i);
}
int interpolations_max = 0;
static void R_SetInterpolation(interpolation_type_e type, void *posptr)
{
int i;
if (!movement_smooth)
return;
if (numinterpolations >= interpolations_max) {
interpolations_max = interpolations_max ? interpolations_max * 2 : 256;
oldipos = (fixed2_t*)realloc(oldipos, sizeof(*oldipos) * interpolations_max);
bakipos = (fixed2_t*)realloc(bakipos, sizeof(*bakipos) * interpolations_max);
curipos = (interpolation_t*)realloc(curipos, sizeof(*curipos) * interpolations_max);
}
for(i = numinterpolations-1; i >= 0; i--)
if (curipos[i].address == posptr && curipos[i].type == type)
return;
curipos[numinterpolations].address = posptr;
curipos[numinterpolations].type = type;
R_CopyInterpToOld (numinterpolations);
numinterpolations++;
}
static void R_StopInterpolation(interpolation_type_e type, void *posptr)
{
int i;
if (!movement_smooth)
return;
for(i=numinterpolations-1; i>= 0; --i)
{
if (curipos[i].address == posptr && curipos[i].type == type)
{
numinterpolations--;
oldipos[i][0] = oldipos[numinterpolations][0];
oldipos[i][1] = oldipos[numinterpolations][1];
bakipos[i][0] = bakipos[numinterpolations][0];
bakipos[i][1] = bakipos[numinterpolations][1];
curipos[i] = curipos[numinterpolations];
break;
}
}
}
void R_StopAllInterpolations(void)
{
int i;
if (!movement_smooth)
return;
for(i=numinterpolations-1; i>= 0; --i)
{
numinterpolations--;
oldipos[i][0] = oldipos[numinterpolations][0];
oldipos[i][1] = oldipos[numinterpolations][1];
bakipos[i][0] = bakipos[numinterpolations][0];
bakipos[i][1] = bakipos[numinterpolations][1];
curipos[i] = curipos[numinterpolations];
}
}
void R_DoInterpolations(fixed_t smoothratio)
{
int i;
if (!movement_smooth)
return;
if (smoothratio == FRACUNIT)
{
didInterp = false;
return;
}
didInterp = true;
for (i = numinterpolations-1; i >= 0; --i)
{
R_DoAnInterpolation (i, smoothratio);
}
}
void R_RestoreInterpolations()
{
int i;
if (!movement_smooth)
return;
if (didInterp)
{
didInterp = false;
for (i = numinterpolations-1; i >= 0; --i)
{
R_CopyBakToInterp (i);
}
}
}
void R_ActivateSectorInterpolations()
{
int i;
sector_t *sec;
if (!movement_smooth)
return;
for (i=0, sec = sectors ; i<numsectors ; i++,sec++)
{
if (sec->floordata)
R_SetInterpolation (INTERP_SectorFloor, sec);
if (sec->ceilingdata)
R_SetInterpolation (INTERP_SectorCeiling, sec);
}
}
static void R_InterpolationGetData(thinker_t *th,
interpolation_type_e *type1, interpolation_type_e *type2,
void **posptr1, void **posptr2)
{
*posptr1 = NULL;
*posptr2 = NULL;
if (th->function == T_MoveFloor)
{
*type1 = INTERP_SectorFloor;
*posptr1 = ((floormove_t *)th)->sector;
}
else
if (th->function == T_PlatRaise)
{
*type1 = INTERP_SectorFloor;
*posptr1 = ((plat_t *)th)->sector;
}
else
if (th->function == T_MoveCeiling)
{
*type1 = INTERP_SectorCeiling;
*posptr1 = ((ceiling_t *)th)->sector;
}
else
if (th->function == T_VerticalDoor)
{
*type1 = INTERP_SectorCeiling;
*posptr1 = ((vldoor_t *)th)->sector;
}
else
if (th->function == T_MoveElevator)
{
*type1 = INTERP_SectorFloor;
*posptr1 = ((elevator_t *)th)->sector;
*type2 = INTERP_SectorCeiling;
*posptr2 = ((elevator_t *)th)->sector;
}
else
if (th->function == T_Scroll)
{
switch (((scroll_t *)th)->type)
{
case sc_side:
*type1 = INTERP_WallPanning;
*posptr1 = sides + ((scroll_t *)th)->affectee;
break;
case sc_floor:
*type1 = INTERP_FloorPanning;
*posptr1 = sectors + ((scroll_t *)th)->affectee;
break;
case sc_ceiling:
*type1 = INTERP_CeilingPanning;
*posptr1 = sectors + ((scroll_t *)th)->affectee;
break;
default: ;
}
}
}
void R_ActivateThinkerInterpolations(thinker_t *th)
{
void *posptr1;
void *posptr2;
interpolation_type_e type1, type2;
if (!movement_smooth)
return;
R_InterpolationGetData(th, &type1, &type2, &posptr1, &posptr2);
if(posptr1)
{
R_SetInterpolation (type1, posptr1);
if(posptr2)
R_SetInterpolation (type2, posptr2);
}
}
void R_StopInterpolationIfNeeded(thinker_t *th)
{
void *posptr1;
void *posptr2;
interpolation_type_e type1, type2;
if (!movement_smooth)
return;
R_InterpolationGetData(th, &type1, &type2, &posptr1, &posptr2);
if(posptr1)
{
R_StopInterpolation (type1, posptr1);
if(posptr2)
R_StopInterpolation (type2, posptr2);
}
}