gzdoom-last-svn/src/r_main.cpp

1834 lines
45 KiB
C++
Raw Normal View History

// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// $Id:$
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This source is available for distribution and/or modification
// only under the terms of the DOOM Source Code License as
// published by id Software. All rights reserved.
//
// The source is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
// for more details.
//
// $Log:$
//
// DESCRIPTION:
// Rendering main loop and setup functions,
// utility functions (BSP, geometry, trigonometry).
// See tables.c, too.
//
//-----------------------------------------------------------------------------
// HEADER FILES ------------------------------------------------------------
#include <stdlib.h>
#include <math.h>
#include "templates.h"
#include "m_alloc.h"
#include "doomdef.h"
#include "d_net.h"
#include "doomstat.h"
#include "m_random.h"
#include "m_bbox.h"
#include "p_local.h"
#include "r_local.h"
#include "r_sky.h"
#include "st_stuff.h"
#include "c_cvars.h"
#include "v_video.h"
#include "stats.h"
#include "i_video.h"
#include "i_system.h"
#include "a_sharedglobal.h"
#include "r_translate.h"
Update to ZDoom r813, including: - Added copyright/license headers to a few files. - Fixed: ACS SetMugShotState needs to check the StatusBar pointer for the proper object type. - Move SBarInfo loading code in d_main.cpp into a static method of DSBarInfo. - Removed dobject.err from the repository. It only contained a list of compiler errors for some very old version of dobject.cpp. - Fixed: A_JumpIfCloser was missing a z-check. - Added Blzut3's SBARINFO update #13: - Split sbarinfo.cpp into two files sbarinfo_display.cpp and sbarinfo_parser.cpp - Rewrote the mug shot system for SBarInfo to allow for scripting and custom states for different means of death. - SBarInfo now loads all SBarInfo lumps instead of just the last one. Clashing status bar definitions will now be cleared before the bar is read. - Fixed: When using transparency with bars the new drawing method (bg over fg) didn't work. In the case that the border value is set to 0 it will revert to the old method (fg over bg). - Fixed: drawbar lost any high res information it was given. - Added: ACS command SetMugShotState(str state) which sets the mug shot state for the activating player. - Added: keepoffsets flag to drawbar. When set the offsets in the fg image will also be applied when displaying the bar. - Fixed the TArray serializer declaration. (Thank you for your warnings, GCC! ;-) - Changed root sector marking so that it can happen incrementally. - Fixed: The TArray serializer needs to be declared as a friend of TArray in order to be able to access its fields. - Since there are no backwards compatibility issues due to savegame version bumping I closed all gaps in the level flag set. - Bumped min. Savegame version and Netgame version for 3dMidtex related changes. - Changed Jump and Crouch DMFlags into 3-way switches: 0: map default, 1: off, 2: on. Since I needed new bits the rest of the DMFlag bit values had to be changed as a result. - fixed: PTR_SlideTraverse didn't check ML_BLOCKMONSTERS for sliding actors without MF3_NOBLOCKMONST. - Added MAPINFO commands 'checkswitchrange' and 'nocheckswitchrange' that can enable or disable switch range checking globally per map. - Changed ML_3DMIDTEX to force ML_CHECKSWITCHRANGE. - Added a ML_CHECKSWITCHRANGE flag which allows checking whether the player can actually reach the switch he wants to use. - Made DActiveButton::EWhere global so that I can use it outside thr DActiveButton class. - Changed P_LineOpening to pass its result in a struct instead of global variables. - Added Eternity's 3DMIDTEX feature (no Eternity code used though.) It should be feature complete with the exception of the ML_BLOCKMONSTERS flag handling. That particular part of Eternity's implementation is sub-optimal because it hijacks an existing flag and doesn't seem to make much sense to me. Maybe I'll implement it as a separate flag later. git-svn-id: http://mancubus.net/svn/hosted/gzdoom/trunk@62 b0f79afe-0144-0410-b225-9a4edf0717df
2008-03-19 11:19:03 +00:00
#include "p_3dmidtex.h"
- Added Skulltag's texture compression feature. Update to ZDoom r1024: - Fixed: There was still an inventory bar check in FMugShot::GetFace() after separating it from DDoomStatusBar. - Fixed: When following links in S_StartSound(), the function used sfx instead of S_Sfx as the array base for getting the NearLimit. - Repositioned the declaration of the file string in D_DoomMain() so that it won't be left on the stack at exit. - Fixed: PSymbol needs a virtual destructor so that PSymbolActionFunction can free its Arguments. - Symbols for native classes are now freed on exit. - Removed the 8-character limit on endpic names from the parser. (Though it might still be present in the texture manager; I don't remember.) - Fixed: EndSequence needs a proper constructor. - Fixed: The EndSequence structure was not fully initialized. - While doing the interpolation rewrite I noticed that DScroller and DPolyAction were doing some things in their destructor that needed to be done in the Destroy method. - Rewrote the interpolation code. Interpolations are no longer some objects that are separate from the rest of the engine. Instead, they are owned by the thinkers starting them. Also, polyobjects only spawn a single interpolation for each polyobject instead of a single one for each vertex. Also, different types of interpolation objects are used for different types of interpolation so that they can do some additional work if eventually needed. git-svn-id: http://mancubus.net/svn/hosted/gzdoom/trunk@117 b0f79afe-0144-0410-b225-9a4edf0717df
2008-06-08 09:24:55 +00:00
#include "r_interpolate.h"
#include "gl/gl_data.h"
#include "gl/gl_texture.h"
#include "gl/gl_functions.h"
// MACROS ------------------------------------------------------------------
#if 0
#define TEST_X 32343794
#define TEST_Y 111387517
#define TEST_Z 2164524
#define TEST_ANGLE 2468347904
#endif
// TYPES -------------------------------------------------------------------
struct InterpolationViewer
{
AActor *ViewActor;
int otic;
fixed_t oviewx, oviewy, oviewz;
fixed_t nviewx, nviewy, nviewz;
int oviewpitch, nviewpitch;
angle_t oviewangle, nviewangle;
};
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
void R_SpanInitData ();
void RP_RenderBSPNode (void *node);
bool RP_SetupFrame (bool backside);
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
static void R_Shutdown();
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
extern bool DrawFSHUD; // [RH] Defined in d_main.cpp
extern short *openings;
extern bool r_fakingunderwater;
extern "C" int fuzzviewheight;
EXTERN_CVAR (Bool, r_particles)
EXTERN_CVAR (Bool, cl_capfps)
// PRIVATE DATA DECLARATIONS -----------------------------------------------
static float CurrentVisibility = 8.f;
static fixed_t MaxVisForWall;
static fixed_t MaxVisForFloor;
static FRandom pr_torchflicker ("TorchFlicker");
static TArray<InterpolationViewer> PastViewers;
static int centerxwide;
static bool polyclipped;
static bool r_showviewer;
bool r_dontmaplines;
// PUBLIC DATA DEFINITIONS -------------------------------------------------
CVAR (String, r_viewsize, "", CVAR_NOSET)
CVAR (Int, r_polymost, 0, 0)
CVAR (Bool, r_deathcamera, false, CVAR_ARCHIVE)
fixed_t r_BaseVisibility;
fixed_t r_WallVisibility;
fixed_t r_FloorVisibility;
float r_TiltVisibility;
fixed_t r_SpriteVisibility;
fixed_t r_ParticleVisibility;
fixed_t r_SkyVisibility;
fixed_t r_TicFrac; // [RH] Fractional tic to render
DWORD r_FrameTime; // [RH] Time this frame started drawing (in ms)
bool r_NoInterpolate;
angle_t LocalViewAngle;
int LocalViewPitch;
bool LocalKeyboardTurner;
float LastFOV;
int WidescreenRatio;
fixed_t GlobVis;
fixed_t FocalTangent;
fixed_t FocalLengthX;
fixed_t FocalLengthY;
float FocalLengthXfloat;
int viewangleoffset;
int validcount = 1; // increment every time a check is made
FDynamicColormap*basecolormap; // [RH] colormap currently drawing with
int fixedlightlev;
lighttable_t *fixedcolormap;
float WallTMapScale;
float WallTMapScale2;
extern "C" {
int centerx;
int centery;
}
DCanvas *RenderTarget; // [RH] canvas to render to
bool bRenderingToCanvas; // [RH] True if rendering to a special canvas
fixed_t globaluclip, globaldclip;
fixed_t centerxfrac;
fixed_t centeryfrac;
fixed_t yaspectmul;
float iyaspectmulfloat;
fixed_t InvZtoScale;
// just for profiling purposes
int framecount;
int linecount;
int loopcount;
fixed_t viewx;
fixed_t viewy;
fixed_t viewz;
int viewpitch;
int otic;
angle_t viewangle;
sector_t *viewsector;
fixed_t viewcos, viewtancos;
fixed_t viewsin, viewtansin;
AActor *camera; // [RH] camera to draw from. doesn't have to be a player
int r_Yaspect = 200; // Why did I make this a variable? It's never set anywhere.
//
// precalculated math tables
//
int FieldOfView = 2048; // Fineangles in the SCREENWIDTH wide window
// The xtoviewangleangle[] table maps a screen pixel
// to the lowest viewangle that maps back to x ranges
// from clipangle to -clipangle.
angle_t xtoviewangle[MAXWIDTH+1];
int extralight; // bumped light from gun blasts
bool foggy; // [RH] ignore extralight and fullbright?
int r_actualextralight;
bool setsizeneeded;
int setblocks, setdetail = -1;
fixed_t freelookviewheight;
unsigned int R_OldBlend = ~0;
void (*colfunc) (void);
void (*basecolfunc) (void);
void (*fuzzcolfunc) (void);
void (*transcolfunc) (void);
void (*spanfunc) (void);
void (*hcolfunc_pre) (void);
void (*hcolfunc_post1) (int hx, int sx, int yl, int yh);
void (*hcolfunc_post2) (int hx, int sx, int yl, int yh);
void (STACK_ARGS *hcolfunc_post4) (int sx, int yl, int yh);
cycle_t WallCycles, PlaneCycles, MaskedCycles, WallScanCycles;
FCanvasTextureInfo *FCanvasTextureInfo::List;
// PRIVATE DATA DEFINITIONS ------------------------------------------------
static int lastcenteryfrac;
static bool NoInterpolateView;
// CODE --------------------------------------------------------------------
//==========================================================================
//
// R_PointToAngle
//
// To get a global angle from cartesian coordinates, the coordinates are
// flipped until they are in the first octant of the coordinate system,
// then the y (<=x) is scaled and divided by x to get a tangent (slope)
// value which is looked up in the tantoangle[] table.
//
//==========================================================================
angle_t R_PointToAngle2 (fixed_t x1, fixed_t y1, fixed_t x, fixed_t y)
{
#if 1
// The precision of the code below is abysmal so use the CRT atan2 function instead!
return quickertoint((float)atan2f(y-y1, x-x1) * ANGLE_180/M_PI);
#else
x -= x1;
y -= y1;
if ((x | y) == 0)
{
return 0;
}
fixed_t ax = abs (x);
fixed_t ay = abs (y);
int div;
angle_t angle;
if (ax > ay)
{
swap (ax, ay);
}
div = SlopeDiv (ax, ay);
angle = tantoangle[div];
if (x >= 0)
{
if (y >= 0)
{
if (x > y)
{ // octant 0
return angle;
}
else
{ // octant 1
return ANG90 - 1 - angle;
}
}
else // y < 0
{
if (x > -y)
{ // octant 8
return (angle_t)-(SDWORD)angle;
}
else
{ // octant 7
return ANG270 + angle;
}
}
}
else // x < 0
{
if (y >= 0)
{
if (-x > y)
{ // octant 3
return ANG180 - 1 - angle;
}
else
{ // octant 2
return ANG90 + angle;
}
}
else // y < 0
{
if (x < y)
{ // octant 4
return ANG180 + angle;
}
else
{ // octant 5
return ANG270 - 1 - angle;
}
}
}
#endif
}
//==========================================================================
//
// R_InitPointToAngle
//
//==========================================================================
void R_InitPointToAngle (void)
{
double f;
int i;
//
// slope (tangent) to angle lookup
//
for (i = 0; i <= SLOPERANGE; i++)
{
f = atan2 ((double)i, (double)SLOPERANGE) / (6.28318530718 /* 2*pi */);
tantoangle[i] = (angle_t)(0xffffffff*f);
}
}
//==========================================================================
//
// R_PointToDist2
//
// Returns the distance from (0,0) to some other point. In a
// floating point environment, we'd probably be better off using the
// Pythagorean Theorem to determine the result.
//
// killough 5/2/98: simplified
// [RH] Simplified further [sin (t + 90 deg) == cos (t)]
// Not used. Should it go away?
//
//==========================================================================
fixed_t R_PointToDist2 (fixed_t dx, fixed_t dy)
{
dx = abs (dx);
dy = abs (dy);
if ((dx | dy) == 0)
{
return 0;
}
if (dy > dx)
{
swap (dx, dy);
}
return FixedDiv (dx, finecosine[tantoangle[FixedDiv (dy, dx) >> DBITS] >> ANGLETOFINESHIFT]);
}
//==========================================================================
//
// R_InitTables
//
//==========================================================================
void R_InitTables (void)
{
int i;
const double pimul = PI*2/FINEANGLES;
// viewangle tangent table
finetangent[0] = (angle_t)(FRACUNIT*tan ((0.5-FINEANGLES/4)*pimul)+0.5);
for (i = 1; i < FINEANGLES/2; i++)
{
finetangent[i] = (angle_t)(FRACUNIT*tan ((i-FINEANGLES/4)*pimul)+0.5);
}
// finesine table
for (i = 0; i < FINEANGLES/4; i++)
{
finesine[i] = (angle_t)(FRACUNIT * sin (i*pimul));
}
for (i = 0; i < FINEANGLES/4; i++)
{
finesine[i+FINEANGLES/4] = finesine[FINEANGLES/4-1-i];
}
for (i = 0; i < FINEANGLES/2; i++)
{
finesine[i+FINEANGLES/2] = -finesine[i];
}
finesine[FINEANGLES/4] = FRACUNIT;
finesine[FINEANGLES*3/4] = -FRACUNIT;
memcpy (&finesine[FINEANGLES], &finesine[0], sizeof(angle_t)*FINEANGLES/4);
}
//==========================================================================
//
// R_InitTextureMapping
//
//==========================================================================
void R_InitTextureMapping ()
{
int i;
fixed_t slope;
int fov = FieldOfView;
// For widescreen displays, increase the FOV so that the middle part of the
// screen that would be visible on a 4:3 display has the requested FOV.
if (centerxwide != centerx)
{ // centerxwide is what centerx would be if the display was not widescreen
fov = int(atan(double(centerx)*tan(double(fov)*M_PI/(FINEANGLES))/double(centerxwide))*(FINEANGLES)/M_PI);
if (fov > 170*FINEANGLES/360)
fov = 170*FINEANGLES/360;
}
/*
default: break;
case 1: fov = MIN (fov * 512/433, 170 * FINEANGLES / 360); break; // 16:9
case 2: fov = MIN (fov * 512/459, 170 * FINEANGLES / 360); break; // 16:10
}
*/
const int hitan = finetangent[FINEANGLES/4+fov/2];
// Calc focallength so FieldOfView fineangles covers viewwidth.
FocalTangent = hitan;
FocalLengthX = FixedDiv (centerxfrac, hitan);
FocalLengthY = Scale (centerxfrac, yaspectmul, hitan);
FocalLengthXfloat = (float)FocalLengthX / 65536.f;
// Now generate xtoviewangle for sky texture mapping.
// [RH] Do not generate viewangletox, because texture mapping is no
// longer done with trig, so it's not needed.
const int t = MIN<int> ((FocalLengthX >> FRACBITS) + centerx, viewwidth);
const fixed_t slopestep = hitan / centerx;
const fixed_t dfocus = FocalLengthX >> DBITS;
for (i = centerx, slope = 0; i <= t; i++, slope += slopestep)
{
xtoviewangle[i] = (angle_t)-(signed)tantoangle[slope >> DBITS];
}
for (; i <= viewwidth; i++)
{
xtoviewangle[i] = ANG270+tantoangle[dfocus / (i - centerx)];
}
for (i = 0; i < centerx; i++)
{
xtoviewangle[i] = (angle_t)(-(signed)xtoviewangle[viewwidth-i-1]);
}
}
//==========================================================================
//
// R_SetFOV
//
// Changes the field of view in degrees
//
//==========================================================================
void R_SetFOV (float fov)
{
if (fov < 5.f)
fov = 5.f;
else if (fov > 170.f)
fov = 170.f;
if (fov != LastFOV)
{
LastFOV = fov;
FieldOfView = (int)(fov * (float)FINEANGLES / 360.f);
setsizeneeded = true;
}
}
//==========================================================================
//
// R_GetFOV
//
// Returns the current field of view in degrees
//
//==========================================================================
float R_GetFOV ()
{
return LastFOV;
}
//==========================================================================
//
// R_SetVisibility
//
// Changes how rapidly things get dark with distance
//
//==========================================================================
void R_SetVisibility (float vis)
{
// Allow negative visibilities, just for novelty's sake
//vis = clamp (vis, -204.7f, 204.7f);
CurrentVisibility = vis;
if (FocalTangent == 0)
{ // If r_visibility is called before the renderer is all set up, don't
// divide by zero. This will be called again later, and the proper
// values can be initialized then.
return;
}
r_BaseVisibility = toint (vis * 65536.f);
// Prevent overflow on walls
if (r_BaseVisibility < 0 && r_BaseVisibility < -MaxVisForWall)
r_WallVisibility = -MaxVisForWall;
else if (r_BaseVisibility > 0 && r_BaseVisibility > MaxVisForWall)
r_WallVisibility = MaxVisForWall;
else
r_WallVisibility = r_BaseVisibility;
r_WallVisibility = FixedMul (Scale (InvZtoScale, SCREENWIDTH*(BaseRatioSizes[WidescreenRatio][1]<<detailyshift),
(viewwidth<<detailxshift)*SCREENHEIGHT*3), FixedMul (r_WallVisibility, FocalTangent));
// Prevent overflow on floors/ceilings. Note that the calculation of
// MaxVisForFloor means that planes less than two units from the player's
// view could still overflow, but there is no way to totally eliminate
// that while still using fixed point math.
if (r_BaseVisibility < 0 && r_BaseVisibility < -MaxVisForFloor)
r_FloorVisibility = -MaxVisForFloor;
else if (r_BaseVisibility > 0 && r_BaseVisibility > MaxVisForFloor)
r_FloorVisibility = MaxVisForFloor;
else
r_FloorVisibility = r_BaseVisibility;
r_FloorVisibility = Scale (160*FRACUNIT, r_FloorVisibility, FocalLengthY);
r_TiltVisibility = vis * (float)FocalTangent * (16.f * 320.f) / (float)viewwidth;
r_SpriteVisibility = r_WallVisibility;
}
//==========================================================================
//
// R_GetVisibility
//
//==========================================================================
float R_GetVisibility ()
{
return CurrentVisibility;
}
//==========================================================================
//
// R_SetViewSize
//
// Do not really change anything here, because it might be in the middle
// of a refresh. The change will take effect next refresh.
//
//==========================================================================
void R_SetViewSize (int blocks)
{
setsizeneeded = true;
setblocks = blocks;
}
//==========================================================================
//
// CVAR r_detail
//
// Selects a pixel doubling mode
//
//==========================================================================
CUSTOM_CVAR (Int, r_detail, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
{
static bool badrecovery = false;
if (badrecovery)
{
badrecovery = false;
return;
}
if (self < 0 || self > 3)
{
Printf ("Bad detail mode. (Use 0-3)\n");
badrecovery = true;
self = (detailyshift << 1) | detailxshift;
return;
}
setdetail = self;
setsizeneeded = true;
}
//==========================================================================
//
// R_SetDetail
//
//==========================================================================
void R_SetDetail (int detail)
{
detailxshift = detail & 1;
detailyshift = (detail >> 1) & 1;
}
//==========================================================================
//
// R_SetWindow
//
//==========================================================================
void R_SetWindow (int windowSize, int fullWidth, int fullHeight, int stHeight)
{
int virtheight, virtwidth;
if (windowSize >= 11)
{
realviewwidth = fullWidth;
freelookviewheight = realviewheight = fullHeight;
}
else if (windowSize == 10)
{
realviewwidth = fullWidth;
realviewheight = stHeight;
freelookviewheight = fullHeight;
}
else
{
realviewwidth = ((setblocks*fullWidth)/10) & (~15);
realviewheight = ((setblocks*stHeight)/10)&~7;
freelookviewheight = ((setblocks*fullHeight)/10)&~7;
}
// If the screen is approximately 16:9 or 16:10, consider it widescreen.
WidescreenRatio = CheckRatio (fullWidth, fullHeight);
DrawFSHUD = (windowSize == 11);
viewwidth = realviewwidth >> detailxshift;
viewheight = realviewheight >> detailyshift;
fuzzviewheight = viewheight - 2; // Maximum row the fuzzer can draw to
freelookviewheight >>= detailyshift;
halfviewwidth = (viewwidth >> 1) - 1;
if (!bRenderingToCanvas)
{ // Set r_viewsize cvar to reflect the current view size
UCVarValue value;
char temp[16];
Update to ZDoom r1083. Not fully tested yet! - Converted most sprintf (and all wsprintf) calls to either mysnprintf or FStrings, depending on the situation. - Changed the strings in the wbstartstruct to be FStrings. - Changed myvsnprintf() to output nothing if count is greater than INT_MAX. This is so that I can use a series of mysnprintf() calls and advance the pointer for each one. Once the pointer goes beyond the end of the buffer, the count will go negative, but since it's an unsigned type it will be seen as excessively huge instead. This should not be a problem, as there's no reason for ZDoom to be using text buffers larger than 2 GB anywhere. - Ripped out the disabled bit from FGameConfigFile::MigrateOldConfig(). - Changed CalcMapName() to return an FString instead of a pointer to a static buffer. - Changed startmap in d_main.cpp into an FString. - Changed CheckWarpTransMap() to take an FString& as the first argument. - Changed d_mapname in g_level.cpp into an FString. - Changed DoSubstitution() in ct_chat.cpp to place the substitutions in an FString. - Fixed: The MAPINFO parser wrote into the string buffer to construct a map name when given a Hexen map number. This was fine with the old scanner code, but only a happy coincidence prevents it from crashing with the new code. - Added the 'B' conversion specifier to StringFormat::VWorker() for printing binary numbers. - Added CMake support for building with MinGW, MSYS, and NMake. Linux support is probably broken until I get around to booting into Linux again. Niceties provided over the existing Makefiles they're replacing: * All command-line builds can use the same build system, rather than having a separate one for MinGW and another for Linux. * Microsoft's NMake tool is supported as a target. * Progress meters. * Parallel makes work from a fresh checkout without needing to be primed first with a single-threaded make. * Porting to other architectures should be simplified, whenever that day comes. - Replaced the makewad tool with zipdir. This handles the dependency tracking itself instead of generating an external makefile to do it, since I couldn't figure out how to generate a makefile with an external tool and include it with a CMake-generated makefile. Where makewad used a master list of files to generate the package file, zipdir just zips the entire contents of one or more directories. git-svn-id: http://mancubus.net/svn/hosted/gzdoom/trunk@138 b0f79afe-0144-0410-b225-9a4edf0717df
2008-07-23 18:35:55 +00:00
mysnprintf (temp, countof(temp), "%d x %d", viewwidth, viewheight);
value.String = temp;
r_viewsize.ForceSet (value, CVAR_String);
}
lastcenteryfrac = 1<<30;
centery = viewheight/2;
centerx = viewwidth/2;
centerxfrac = centerx<<FRACBITS;
centeryfrac = centery<<FRACBITS;
virtwidth = fullWidth >> detailxshift;
virtheight = fullHeight >> detailyshift;
if (WidescreenRatio & 4)
{
virtheight = virtheight * BaseRatioSizes[WidescreenRatio][3] / 48;
centerxwide = centerx;
}
else
{
virtwidth = virtwidth * BaseRatioSizes[WidescreenRatio][3] / 48;
centerxwide = centerx * BaseRatioSizes[WidescreenRatio][3] / 48;
}
yaspectmul = Scale ((320<<FRACBITS), virtheight, r_Yaspect * virtwidth);
iyaspectmulfloat = (float)virtwidth * r_Yaspect / 320.f / (float)virtheight;
InvZtoScale = yaspectmul * centerx;
WallTMapScale = (float)centerx * 32.f;
WallTMapScale2 = iyaspectmulfloat * 2.f / (float)centerx;
// psprite scales
pspritexscale = (centerxwide << FRACBITS) / 160;
pspriteyscale = FixedMul (pspritexscale, yaspectmul);
pspritexiscale = FixedDiv (FRACUNIT, pspritexscale);
// thing clipping
clearbufshort (screenheightarray, viewwidth, (short)viewheight);
// [RH] Sky height fix for screens not 200 (or 240) pixels tall
R_InitSkyMap ();
R_InitTextureMapping ();
MaxVisForWall = FixedMul (Scale (InvZtoScale, SCREENWIDTH*(r_Yaspect<<detailyshift),
(viewwidth<<detailxshift)*SCREENHEIGHT), FocalTangent);
MaxVisForWall = FixedDiv (0x7fff0000, MaxVisForWall);
MaxVisForFloor = Scale (FixedDiv (0x7fff0000, viewheight<<(FRACBITS-2)), FocalLengthY, 160*FRACUNIT);
// Reset r_*Visibility vars
R_SetVisibility (R_GetVisibility ());
}
//==========================================================================
//
// R_ExecuteSetViewSize
//
//==========================================================================
void R_ExecuteSetViewSize ()
{
setsizeneeded = false;
BorderNeedRefresh = screen->GetPageCount ();
if (setdetail >= 0)
{
R_SetDetail (setdetail);
setdetail = -1;
}
R_SetWindow (setblocks, SCREENWIDTH, SCREENHEIGHT, ST_Y);
// Handle resize, e.g. smaller view windows with border and/or status bar.
viewwindowx = (screen->GetWidth() - (viewwidth<<detailxshift))>>1;
// Same with base row offset.
viewwindowy = ((viewwidth<<detailxshift) == screen->GetWidth()) ?
0 : (ST_Y-(viewheight<<detailyshift)) >> 1;
}
//==========================================================================
//
// CVAR screenblocks
//
// Selects the size of the visible window
//
//==========================================================================
CUSTOM_CVAR (Int, screenblocks, 10, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
{
if (self > 12)
self = 12;
else if (self < 3)
self = 3;
else
R_SetViewSize (self);
}
//==========================================================================
//
// CVAR r_columnmethod
//
// Selects which version of the seg renderers to use.
//
//==========================================================================
CUSTOM_CVAR (Int, r_columnmethod, 1, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
{
if (self != 0 && self != 1)
{
self = 1;
}
else
{ // Trigger the change
r_detail.Callback ();
}
}
//==========================================================================
//
// R_Init
//
//==========================================================================
void R_Init ()
{
atterm (R_Shutdown);
R_InitData ();
gl_ParseDefs();
R_InitPointToAngle ();
R_InitTables ();
// viewwidth / viewheight are set by the defaults
R_SetViewSize (screenblocks);
R_InitPlanes ();
R_InitTranslationTables ();
R_InitParticles (); // [RH] Setup particle engine
R_InitColumnDrawers ();
colfunc = basecolfunc = R_DrawColumn;
fuzzcolfunc = R_DrawFuzzColumn;
transcolfunc = R_DrawTranslatedColumn;
spanfunc = R_DrawSpan;
// [RH] Horizontal column drawers
hcolfunc_pre = R_DrawColumnHoriz;
hcolfunc_post1 = rt_map1col;
hcolfunc_post4 = rt_map4cols;
framecount = 0;
}
//==========================================================================
//
// R_Shutdown
//
//==========================================================================
static void R_Shutdown ()
{
R_DeinitParticles();
R_DeinitTranslationTables();
R_DeinitPlanes();
R_DeinitData();
}
//==========================================================================
//
// I am keeping both the original nodes from the WAD and the ones
// created for the GL renderer. THe original set is only being used
// to get the sector for in-game positioning of actors but not for rendering.
//
// Unfortunately this is necessary because ZDBSP is much more sensitive
// to sloppy mapping practices that produce overlapping sectors.
// The crane in P:AR E1M3 is a good example that would be broken If
// I didn't do this.
//
//==========================================================================
//==========================================================================
//
// P_PointInSubsector
//
//==========================================================================
subsector_t *P_PointInSubsector (fixed_t x, fixed_t y)
{
node_t *node;
int side;
// single subsector is a special case
if (numgamenodes == 0)
return gamesubsectors;
node = gamenodes + numgamenodes - 1;
do
{
side = R_PointOnSide (x, y, node);
node = (node_t *)node->children[side];
}
while (!((size_t)node & 1));
return (subsector_t *)((BYTE *)node - 1);
}
//==========================================================================
//
// R_PointInSubsector
//
//==========================================================================
subsector_t *R_PointInSubsector (fixed_t x, fixed_t y)
{
node_t *node;
int side;
// single subsector is a special case
if (numnodes == 0)
return subsectors;
node = nodes + numnodes - 1;
do
{
side = R_PointOnSide (x, y, node);
node = (node_t *)node->children[side];
}
while (!((size_t)node & 1));
return (subsector_t *)((BYTE *)node - 1);
}
//==========================================================================
//
// R_InterpolateView
//
//==========================================================================
//CVAR (Int, tf, 0, 0)
EXTERN_CVAR (Bool, cl_noprediction)
void R_InterpolateView (player_t *player, fixed_t frac, InterpolationViewer *iview)
{
// frac = tf;
if (NoInterpolateView)
{
NoInterpolateView = false;
iview->oviewx = iview->nviewx;
iview->oviewy = iview->nviewy;
iview->oviewz = iview->nviewz;
iview->oviewpitch = iview->nviewpitch;
iview->oviewangle = iview->nviewangle;
}
viewx = iview->oviewx + FixedMul (frac, iview->nviewx - iview->oviewx);
viewy = iview->oviewy + FixedMul (frac, iview->nviewy - iview->oviewy);
viewz = iview->oviewz + FixedMul (frac, iview->nviewz - iview->oviewz);
if (player != NULL &&
player - players == consoleplayer &&
camera == player->mo &&
!demoplayback &&
iview->nviewx == camera->x &&
iview->nviewy == camera->y &&
!(player->cheats & (CF_TOTALLYFROZEN|CF_FROZEN)) &&
player->playerstate == PST_LIVE &&
player->mo->reactiontime == 0 &&
!NoInterpolateView &&
!paused &&
(!netgame || !cl_noprediction) &&
!LocalKeyboardTurner)
{
viewangle = iview->nviewangle + (LocalViewAngle & 0xFFFF0000);
fixed_t delta = -(signed)(LocalViewPitch & 0xFFFF0000);
viewpitch = iview->nviewpitch;
if (delta > 0)
{
// Avoid overflowing viewpitch (can happen when a netgame is stalled)
if (viewpitch + delta <= viewpitch)
{
viewpitch = +ANGLE_1*MAX_DN_ANGLE;
}
else
{
viewpitch = MIN(viewpitch + delta, +ANGLE_1*MAX_DN_ANGLE);
}
}
else if (delta < 0)
{
// Avoid overflowing viewpitch (can happen when a netgame is stalled)
if (viewpitch + delta >= viewpitch)
{
viewpitch = -ANGLE_1*MAX_UP_ANGLE;
}
else
{
viewpitch = MAX(viewpitch + delta, -ANGLE_1*MAX_UP_ANGLE);
}
}
}
else
{
viewpitch = iview->oviewpitch + FixedMul (frac, iview->nviewpitch - iview->oviewpitch);
viewangle = iview->oviewangle + FixedMul (frac, iview->nviewangle - iview->oviewangle);
}
// Due to interpolation this is not necessarily the same as the sector the camera is in.
viewsector = R_PointInSubsector(viewx, viewy)->sector;
}
//==========================================================================
//
// R_ResetViewInterpolation
//
//==========================================================================
void R_ResetViewInterpolation ()
{
NoInterpolateView = true;
}
//==========================================================================
//
// R_SetViewAngle
//
//==========================================================================
void R_SetViewAngle ()
{
angle_t ang = viewangle >> ANGLETOFINESHIFT;
viewsin = finesine[ang];
viewcos = finecosine[ang];
viewtansin = FixedMul (FocalTangent, viewsin);
viewtancos = FixedMul (FocalTangent, viewcos);
}
//==========================================================================
//
// FindPastViewer
//
//==========================================================================
static InterpolationViewer *FindPastViewer (AActor *actor)
{
for (unsigned int i = 0; i < PastViewers.Size(); ++i)
{
if (PastViewers[i].ViewActor == actor)
{
return &PastViewers[i];
}
}
// Not found, so make a new one
InterpolationViewer iview = { 0 };
iview.ViewActor = actor;
iview.otic = -1;
return &PastViewers[PastViewers.Push (iview)];
}
//==========================================================================
//
// R_FreePastViewers
//
//==========================================================================
void R_FreePastViewers ()
{
PastViewers.Clear ();
}
//==========================================================================
//
// R_ClearPastViewer
//
// If the actor changed in a non-interpolatable way, remove it.
//
//==========================================================================
void R_ClearPastViewer (AActor *actor)
{
for (unsigned int i = 0; i < PastViewers.Size(); ++i)
{
if (PastViewers[i].ViewActor == actor)
{
// Found it, so remove it.
if (i == PastViewers.Size())
{
PastViewers.Delete (i);
}
else
{
PastViewers.Pop (PastViewers[i]);
}
}
}
}
//==========================================================================
//
// R_CopyStackedViewParameters
//
//==========================================================================
void R_CopyStackedViewParameters()
{
stacked_viewx = viewx;
stacked_viewy = viewy;
stacked_viewz = viewz;
stacked_angle = viewangle;
stacked_extralight = extralight;
stacked_visibility = R_GetVisibility();
}
//==========================================================================
//
// R_SetupFrame
//
//==========================================================================
void R_SetupFrame (AActor *actor)
{
if (actor == NULL)
{
I_Error ("Tried to render from a NULL actor.");
}
player_t *player = actor->player;
unsigned int newblend;
InterpolationViewer *iview;
if (player != NULL && player->mo == actor)
{ // [RH] Use camera instead of viewplayer
camera = player->camera;
if (camera == NULL)
{
camera = player->camera = player->mo;
}
if (camera == actor)
{
P_PredictPlayer (player);
}
}
else
{
camera = actor;
}
if (camera == NULL)
{
I_Error ("You lost your body. Bad dehacked work is likely to blame.");
}
iview = FindPastViewer (camera);
int nowtic = I_GetTime (false);
if (iview->otic != -1 && nowtic > iview->otic)
{
iview->otic = nowtic;
iview->oviewx = iview->nviewx;
iview->oviewy = iview->nviewy;
iview->oviewz = iview->nviewz;
iview->oviewpitch = iview->nviewpitch;
iview->oviewangle = iview->nviewangle;
}
if (player != NULL && gamestate != GS_TITLELEVEL &&
((player->cheats & CF_CHASECAM) || (r_deathcamera && camera->health <= 0)) &&
(camera->RenderStyle.BlendOp != STYLEOP_None) &&
!(camera->renderflags & RF_INVISIBLE) &&
camera->sprite != 0) // Sprite 0 is always TNT1
{
// [RH] Use chasecam view
P_AimCamera (camera, iview->nviewx, iview->nviewy, iview->nviewz, viewsector);
r_showviewer = true;
}
else
{
iview->nviewx = camera->x;
iview->nviewy = camera->y;
iview->nviewz = camera->player ? camera->player->viewz : camera->z + camera->GetClass()->Meta.GetMetaFixed(AMETA_CameraHeight);
viewsector = camera->Sector;
r_showviewer = false;
}
iview->nviewpitch = camera->pitch;
if (camera->player != 0)
{
player = camera->player;
}
iview->nviewangle = camera->angle + viewangleoffset;
if (iview->otic == -1 || r_NoInterpolate)
{
R_ResetViewInterpolation ();
iview->otic = nowtic;
}
R_UpdateAnimations (I_MSTime());
r_TicFrac = I_GetTimeFrac (&r_FrameTime);
if (cl_capfps || r_NoInterpolate)
{
r_TicFrac = FRACUNIT;
}
R_InterpolateView (player, r_TicFrac, iview);
#ifdef TEST_X
viewx = TEST_X;
viewy = TEST_Y;
viewz = TEST_Z;
viewangle = TEST_ANGLE;
#endif
R_CopyStackedViewParameters();
R_SetViewAngle ();
- Added Skulltag's texture compression feature. Update to ZDoom r1024: - Fixed: There was still an inventory bar check in FMugShot::GetFace() after separating it from DDoomStatusBar. - Fixed: When following links in S_StartSound(), the function used sfx instead of S_Sfx as the array base for getting the NearLimit. - Repositioned the declaration of the file string in D_DoomMain() so that it won't be left on the stack at exit. - Fixed: PSymbol needs a virtual destructor so that PSymbolActionFunction can free its Arguments. - Symbols for native classes are now freed on exit. - Removed the 8-character limit on endpic names from the parser. (Though it might still be present in the texture manager; I don't remember.) - Fixed: EndSequence needs a proper constructor. - Fixed: The EndSequence structure was not fully initialized. - While doing the interpolation rewrite I noticed that DScroller and DPolyAction were doing some things in their destructor that needed to be done in the Destroy method. - Rewrote the interpolation code. Interpolations are no longer some objects that are separate from the rest of the engine. Instead, they are owned by the thinkers starting them. Also, polyobjects only spawn a single interpolation for each polyobject instead of a single one for each vertex. Also, different types of interpolation objects are used for different types of interpolation so that they can do some additional work if eventually needed. git-svn-id: http://mancubus.net/svn/hosted/gzdoom/trunk@117 b0f79afe-0144-0410-b225-9a4edf0717df
2008-06-08 09:24:55 +00:00
interpolator.DoInterpolations (r_TicFrac);
// Keep the view within the sector's floor and ceiling
fixed_t theZ = viewsector->ceilingplane.ZatPoint (viewx, viewy) - 4*FRACUNIT;
if (viewz > theZ)
{
viewz = theZ;
}
theZ = viewsector->floorplane.ZatPoint (viewx, viewy) + 4*FRACUNIT;
if (viewz < theZ)
{
viewz = theZ;
}
if (!paused)
{
int intensity = DEarthquake::StaticGetQuakeIntensity (camera);
if (intensity != 0)
{
viewx += ((pr_torchflicker() % (intensity<<2))
-(intensity<<1))<<FRACBITS;
viewy += ((pr_torchflicker() % (intensity<<2))
-(intensity<<1))<<FRACBITS;
}
}
extralight = camera->player ? camera->player->extralight : 0;
// killough 3/20/98, 4/4/98: select colormap based on player status
// [RH] Can also select a blend
if (viewsector->heightsec &&
!(viewsector->heightsec->MoreFlags & SECF_IGNOREHEIGHTSEC))
{
const sector_t *s = viewsector->heightsec;
newblend = viewz < s->floorplane.ZatPoint (viewx, viewy)
? s->bottommap
: viewz > s->ceilingplane.ZatPoint (viewx, viewy)
? s->topmap
: s->midmap;
if (APART(newblend) == 0 && newblend >= numfakecmaps)
newblend = 0;
}
else
{
newblend = 0;
}
// [RH] Don't override testblend unless entering a sector with a
// blend different from the previous sector's. Same goes with
// NormalLight's maps pointer.
if (R_OldBlend != newblend)
{
R_OldBlend = newblend;
if (APART(newblend))
{
BaseBlendR = RPART(newblend);
BaseBlendG = GPART(newblend);
BaseBlendB = BPART(newblend);
BaseBlendA = APART(newblend) / 255.f;
NormalLight.Maps = realcolormaps;
}
else
{
NormalLight.Maps = realcolormaps + NUMCOLORMAPS*256*newblend;
BaseBlendR = BaseBlendG = BaseBlendB = 0;
BaseBlendA = 0.f;
}
}
fixedcolormap = NULL;
fixedlightlev = 0;
if (player != NULL && camera == player->mo && player->fixedcolormap)
{
if (player->fixedcolormap < NUMCOLORMAPS)
{
fixedlightlev = player->fixedcolormap*256;
fixedcolormap = NormalLight.Maps;
}
else switch (player->fixedcolormap)
{
case INVERSECOLORMAP:
fixedcolormap = InverseColormap;
break;
case REDCOLORMAP:
fixedcolormap = RedColormap;
break;
case GREENCOLORMAP:
fixedcolormap = GreenColormap;
break;
case GOLDCOLORMAP:
fixedcolormap = GoldColormap;
break;
default:
break;
}
}
// [RH] Inverse light for shooting the Sigil
else if (extralight == INT_MIN)
{
fixedcolormap = InverseColormap;
extralight = 0;
}
// [RH] freelook stuff
{
fixed_t dy;
if (camera != NULL)
{
dy = FixedMul (FocalLengthY, finetangent[(ANGLE_90-viewpitch)>>ANGLETOFINESHIFT]);
}
else
{
dy = 0;
}
centeryfrac = (viewheight << (FRACBITS-1)) + dy;
centery = centeryfrac >> FRACBITS;
globaluclip = FixedDiv (-centeryfrac, InvZtoScale);
globaldclip = FixedDiv ((viewheight<<FRACBITS)-centeryfrac, InvZtoScale);
//centeryfrac &= 0xffff0000;
int e, i;
i = 0;
e = viewheight;
fixed_t focus = FocalLengthY;
fixed_t den;
if (i < centery)
{
den = centeryfrac - (i << FRACBITS) - FRACUNIT/2;
if (e <= centery)
{
do {
yslope[i] = FixedDiv (focus, den);
den -= FRACUNIT;
} while (++i < e);
}
else
{
do {
yslope[i] = FixedDiv (focus, den);
den -= FRACUNIT;
} while (++i < centery);
den = (i << FRACBITS) - centeryfrac + FRACUNIT/2;
do {
yslope[i] = FixedDiv (focus, den);
den += FRACUNIT;
} while (++i < e);
}
}
else
{
den = (i << FRACBITS) - centeryfrac + FRACUNIT/2;
do {
yslope[i] = FixedDiv (focus, den);
den += FRACUNIT;
} while (++i < e);
}
}
P_UnPredictPlayer ();
framecount++;
validcount++;
if (r_polymost)
{
polyclipped = RP_SetupFrame (false);
}
}
//==========================================================================
//
// R_RefreshViewBorder
//
// Draws the border around the player view, if needed.
//
//==========================================================================
void R_RefreshViewBorder ()
{
if (setblocks < 10)
{
if (BorderNeedRefresh)
{
BorderNeedRefresh--;
if (BorderTopRefresh)
{
BorderTopRefresh--;
}
R_DrawViewBorder();
}
else if (BorderTopRefresh)
{
BorderTopRefresh--;
R_DrawTopBorder();
}
}
}
//==========================================================================
//
// R_EnterMirror
//
// [RH] Draw the reflection inside a mirror
//
//==========================================================================
void R_EnterMirror (drawseg_t *ds, int depth)
{
angle_t startang = viewangle;
fixed_t startx = viewx;
fixed_t starty = viewy;
unsigned int mirrorsAtStart = WallMirrors.Size ();
vertex_t *v1 = ds->curline->v1;
// Reflect the current view behind the mirror.
if (ds->curline->linedef->dx == 0)
{ // vertical mirror
viewx = v1->x - startx + v1->x;
}
else if (ds->curline->linedef->dy == 0)
{ // horizontal mirror
viewy = v1->y - starty + v1->y;
}
else
{ // any mirror--use floats to avoid integer overflow
vertex_t *v2 = ds->curline->v2;
float dx = FIXED2FLOAT(v2->x - v1->x);
float dy = FIXED2FLOAT(v2->y - v1->y);
float x1 = FIXED2FLOAT(v1->x);
float y1 = FIXED2FLOAT(v1->y);
float x = FIXED2FLOAT(startx);
float y = FIXED2FLOAT(starty);
// the above two cases catch len == 0
float r = ((x - x1)*dx + (y - y1)*dy) / (dx*dx + dy*dy);
viewx = FLOAT2FIXED((x1 + r * dx)*2 - x);
viewy = FLOAT2FIXED((y1 + r * dy)*2 - y);
}
viewangle = 2*R_PointToAngle2 (ds->curline->v1->x, ds->curline->v1->y,
ds->curline->v2->x, ds->curline->v2->y) - startang;
viewsin = finesine[viewangle>>ANGLETOFINESHIFT];
viewcos = finecosine[viewangle>>ANGLETOFINESHIFT];
viewtansin = FixedMul (FocalTangent, viewsin);
viewtancos = FixedMul (FocalTangent, viewcos);
R_CopyStackedViewParameters();
validcount++;
ActiveWallMirror = ds->curline;
R_ClearPlanes (false);
R_ClearClipSegs (ds->x1, ds->x2 + 1);
memcpy (ceilingclip + ds->x1, openings + ds->sprtopclip, (ds->x2 - ds->x1 + 1)*sizeof(*ceilingclip));
memcpy (floorclip + ds->x1, openings + ds->sprbottomclip, (ds->x2 - ds->x1 + 1)*sizeof(*floorclip));
WindowLeft = ds->x1;
WindowRight = ds->x2;
MirrorFlags = (depth + 1) & 1;
R_RenderBSPNode (nodes + numnodes - 1);
R_DrawPlanes ();
R_DrawSkyBoxes ();
// Allow up to 4 recursions through a mirror
if (depth < 4)
{
unsigned int mirrorsAtEnd = WallMirrors.Size ();
for (; mirrorsAtStart < mirrorsAtEnd; mirrorsAtStart++)
{
R_EnterMirror (drawsegs + WallMirrors[mirrorsAtStart], depth + 1);
}
}
else
{
depth = depth;
}
viewangle = startang;
viewx = startx;
viewy = starty;
}
//==========================================================================
//
// R_SetupBuffer
//
// Precalculate all row offsets and fuzz table.
//
//==========================================================================
void R_SetupBuffer (bool inview)
{
static BYTE *lastbuff = NULL;
int pitch = RenderTarget->GetPitch();
BYTE *lineptr = RenderTarget->GetBuffer() + viewwindowy*pitch + viewwindowx;
if (inview)
{
pitch <<= detailyshift;
}
if (detailxshift)
{
lineptr += viewwidth;
}
if (dc_pitch != pitch || lineptr != lastbuff)
{
if (dc_pitch != pitch)
{
dc_pitch = pitch;
R_InitFuzzTable (pitch);
#ifdef USEASM
ASM_PatchPitch ();
#endif
}
dc_destorg = lineptr;
for (int i = 0; i < RenderTarget->GetHeight(); i++)
{
ylookup[i] = i * pitch;
}
}
}
//==========================================================================
//
// R_RenderActorView
//
//==========================================================================
void R_RenderActorView (AActor *actor, bool dontmaplines)
{
WallCycles = PlaneCycles = MaskedCycles = WallScanCycles = 0;
R_SetupBuffer (true);
R_SetupFrame (actor);
// Clear buffers.
R_ClearClipSegs (0, viewwidth);
R_ClearDrawSegs ();
R_ClearPlanes (true);
R_ClearSprites ();
NetUpdate ();
// [RH] Show off segs if r_drawflat is 1
if (r_drawflat)
{
hcolfunc_pre = R_FillColumnHorizP;
hcolfunc_post1 = rt_copy1col;
hcolfunc_post4 = rt_copy4cols;
colfunc = R_FillColumnP;
spanfunc = R_FillSpan;
}
else
{
hcolfunc_pre = R_DrawColumnHoriz;
hcolfunc_post1 = rt_map1col;
hcolfunc_post4 = rt_map4cols;
colfunc = basecolfunc;
spanfunc = R_DrawSpan;
}
WindowLeft = 0;
WindowRight = viewwidth - 1;
MirrorFlags = 0;
ActiveWallMirror = NULL;
r_dontmaplines = dontmaplines;
// [RH] Hack to make windows into underwater areas possible
r_fakingunderwater = false;
// [RH] Setup particles for this frame
R_FindParticleSubsectors ();
clock (WallCycles);
DWORD savedflags = camera->renderflags;
// Never draw the player unless in chasecam mode
if (!r_showviewer)
{
camera->renderflags |= RF_INVISIBLE;
}
if (r_polymost < 2)
{
R_RenderBSPNode (nodes + numnodes - 1); // The head node is the last node output.
}
camera->renderflags = savedflags;
unclock (WallCycles);
NetUpdate ();
if (viewactive)
{
clock (PlaneCycles);
R_DrawPlanes ();
R_DrawSkyBoxes ();
unclock (PlaneCycles);
// [RH] Walk through mirrors
size_t lastmirror = WallMirrors.Size ();
for (unsigned int i = 0; i < lastmirror; i++)
{
R_EnterMirror (drawsegs + WallMirrors[i], 0);
}
NetUpdate ();
clock (MaskedCycles);
R_DrawMasked ();
unclock (MaskedCycles);
NetUpdate ();
if (r_polymost)
{
RP_RenderBSPNode (nodes + numnodes - 1);
if (polyclipped)
{
RP_SetupFrame (true);
RP_RenderBSPNode (nodes + numnodes - 1);
}
}
}
WallMirrors.Clear ();
- Added Skulltag's texture compression feature. Update to ZDoom r1024: - Fixed: There was still an inventory bar check in FMugShot::GetFace() after separating it from DDoomStatusBar. - Fixed: When following links in S_StartSound(), the function used sfx instead of S_Sfx as the array base for getting the NearLimit. - Repositioned the declaration of the file string in D_DoomMain() so that it won't be left on the stack at exit. - Fixed: PSymbol needs a virtual destructor so that PSymbolActionFunction can free its Arguments. - Symbols for native classes are now freed on exit. - Removed the 8-character limit on endpic names from the parser. (Though it might still be present in the texture manager; I don't remember.) - Fixed: EndSequence needs a proper constructor. - Fixed: The EndSequence structure was not fully initialized. - While doing the interpolation rewrite I noticed that DScroller and DPolyAction were doing some things in their destructor that needed to be done in the Destroy method. - Rewrote the interpolation code. Interpolations are no longer some objects that are separate from the rest of the engine. Instead, they are owned by the thinkers starting them. Also, polyobjects only spawn a single interpolation for each polyobject instead of a single one for each vertex. Also, different types of interpolation objects are used for different types of interpolation so that they can do some additional work if eventually needed. git-svn-id: http://mancubus.net/svn/hosted/gzdoom/trunk@117 b0f79afe-0144-0410-b225-9a4edf0717df
2008-06-08 09:24:55 +00:00
interpolator.RestoreInterpolations ();
// If there is vertical doubling, and the view window is not an even height,
// draw a black line at the bottom of the view window.
if (detailyshift && viewwindowy == 0 && (realviewheight & 1))
{
screen->Clear (0, realviewheight-1, realviewwidth, realviewheight, 0, 0);
}
R_SetupBuffer (false);
}
//==========================================================================
//
// R_RenderViewToCanvas
//
// Pre: Canvas is already locked.
//
//==========================================================================
void R_RenderViewToCanvas (AActor *actor, DCanvas *canvas,
int x, int y, int width, int height, bool dontmaplines)
{
const int saveddetail = detailxshift | (detailyshift << 1);
const bool savedviewactive = viewactive;
detailxshift = detailyshift = 0;
realviewwidth = viewwidth = width;
RenderTarget = canvas;
bRenderingToCanvas = true;
R_SetDetail (0);
R_SetWindow (12, width, height, height);
viewwindowx = x;
viewwindowy = y;
viewactive = true;
R_RenderActorView (actor, dontmaplines);
RenderTarget = screen;
bRenderingToCanvas = false;
R_SetDetail (saveddetail);
R_ExecuteSetViewSize ();
screen->Lock (true);
R_SetupBuffer (false);
screen->Unlock ();
viewactive = savedviewactive;
}
//==========================================================================
//
// FCanvasTextureInfo :: Add
//
// Assigns a camera to a canvas texture.
//
//==========================================================================
Update to ZDoom r1052: - Fixed: Dead players didn't get the MF_CORPSE flag set. - Fixed: The internal definition of Floor_LowerToNearest had incorrect parameter settings. - Fixed: Heretic's ActivatedTimeBomb had the same spawn ID as the inventory item. - fixed: Heretic's mace did not have its spawn ID set. - For controls that are not bound, the customize controls menu now displays a black --- instead of ???. - Applied Gez's BossBrainPatch3. - Fixed: P_BulletSlope() did not return the linetarget. This effected the Sigil, A_JumpIfCloser, and A_JumpIfTargetInLOS. - Fixed all the new warnings tossed out by GCC 4.3. - Fixed: PickNext/PrevWeapon() did not check for NULL player actors. - Fixed compilation issues with GCC. - Removed special case for nobotnodes in MAPINFO. - Added support for ST's QUARTERGRAVITY flag. - Added a generalized version of Skulltag's A_CheckRailReload function. - Fixed: DrawImage didn't take 0 as a valid image index. - Added Gez's RandomSpawner submission with significant changes. - Added optional blocks for MAPINFO map definitions. ZDoom doesn't use this feature itself but it allows other ports based on ZDoom to implement their own sets of options without making such a MAPINFO unreadable by ZDoom. - Fixed: The mugshot would not reset on re-spawn. - Fixed: Picking up a weapon would sometimes not activate the grin. - Changed: Line_SetIdentification will ignore extended parameters when used in maps defined Hexen style in MAPINFO. - Fixed: Ambient sounds didn't pass their point of origin to S_StartSound. - Fixed: UseType was not properly set for textures defined in TEXTURES. - Fixed: You couldn't set an offset for sprites defined in TEXTURES. - Added read barriers to all actor pointers within player_t except for mo, ReadyWeapon and PendingWeapon. - Added a read barrier to player_t::PrewmorphWeapon. - Fixed: After spawning a deathmatch player P_PlayerStartStomp must be called. - Fixed: SpawnThings must check if the players were spawned before calling P_PlayerStartStomp. - Fixed typo in flat scroll interpolation. - Changed FImageCollection to return translated texture indices so that animated icons can be done with it. - Changed FImageCollection to use a TArray to hold its data. - Fixed: SetChanHeadSettings did an assignment instead of comparing the channel ID witg CHAN_CEILING. - Changed sound sequence names for animated doors to FNames. - Automatically fixed: DCeiling didn't properly serialize its texture id. - Replaced integers as texture ID representation with a specific new type to track down all potentially incorrect uses and remaining WORDs used for texture IDs so that more than 32767 or 65535 textures can be defined. git-svn-id: http://mancubus.net/svn/hosted/gzdoom/trunk@124 b0f79afe-0144-0410-b225-9a4edf0717df
2008-06-28 13:29:59 +00:00
void FCanvasTextureInfo::Add (AActor *viewpoint, FTextureID picnum, int fov)
{
FCanvasTextureInfo *probe;
FCanvasTexture *texture;
Update to ZDoom r1052: - Fixed: Dead players didn't get the MF_CORPSE flag set. - Fixed: The internal definition of Floor_LowerToNearest had incorrect parameter settings. - Fixed: Heretic's ActivatedTimeBomb had the same spawn ID as the inventory item. - fixed: Heretic's mace did not have its spawn ID set. - For controls that are not bound, the customize controls menu now displays a black --- instead of ???. - Applied Gez's BossBrainPatch3. - Fixed: P_BulletSlope() did not return the linetarget. This effected the Sigil, A_JumpIfCloser, and A_JumpIfTargetInLOS. - Fixed all the new warnings tossed out by GCC 4.3. - Fixed: PickNext/PrevWeapon() did not check for NULL player actors. - Fixed compilation issues with GCC. - Removed special case for nobotnodes in MAPINFO. - Added support for ST's QUARTERGRAVITY flag. - Added a generalized version of Skulltag's A_CheckRailReload function. - Fixed: DrawImage didn't take 0 as a valid image index. - Added Gez's RandomSpawner submission with significant changes. - Added optional blocks for MAPINFO map definitions. ZDoom doesn't use this feature itself but it allows other ports based on ZDoom to implement their own sets of options without making such a MAPINFO unreadable by ZDoom. - Fixed: The mugshot would not reset on re-spawn. - Fixed: Picking up a weapon would sometimes not activate the grin. - Changed: Line_SetIdentification will ignore extended parameters when used in maps defined Hexen style in MAPINFO. - Fixed: Ambient sounds didn't pass their point of origin to S_StartSound. - Fixed: UseType was not properly set for textures defined in TEXTURES. - Fixed: You couldn't set an offset for sprites defined in TEXTURES. - Added read barriers to all actor pointers within player_t except for mo, ReadyWeapon and PendingWeapon. - Added a read barrier to player_t::PrewmorphWeapon. - Fixed: After spawning a deathmatch player P_PlayerStartStomp must be called. - Fixed: SpawnThings must check if the players were spawned before calling P_PlayerStartStomp. - Fixed typo in flat scroll interpolation. - Changed FImageCollection to return translated texture indices so that animated icons can be done with it. - Changed FImageCollection to use a TArray to hold its data. - Fixed: SetChanHeadSettings did an assignment instead of comparing the channel ID witg CHAN_CEILING. - Changed sound sequence names for animated doors to FNames. - Automatically fixed: DCeiling didn't properly serialize its texture id. - Replaced integers as texture ID representation with a specific new type to track down all potentially incorrect uses and remaining WORDs used for texture IDs so that more than 32767 or 65535 textures can be defined. git-svn-id: http://mancubus.net/svn/hosted/gzdoom/trunk@124 b0f79afe-0144-0410-b225-9a4edf0717df
2008-06-28 13:29:59 +00:00
if (!picnum.isValid())
{
return;
}
texture = static_cast<FCanvasTexture *>(TexMan[picnum]);
if (!texture->bHasCanvas)
{
Printf ("%s is not a valid target for a camera\n", texture->Name);
return;
}
// Is this texture already assigned to a camera?
for (probe = List; probe != NULL; probe = probe->Next)
{
if (probe->Texture == texture)
{
// Yes, change its assignment to this new camera
if (probe->Viewpoint != viewpoint || probe->FOV != fov)
{
texture->bFirstUpdate = true;
}
probe->Viewpoint = viewpoint;
probe->FOV = fov;
return;
}
}
// No, create a new assignment
probe = new FCanvasTextureInfo;
probe->Viewpoint = viewpoint;
probe->Texture = texture;
probe->PicNum = picnum;
probe->FOV = fov;
probe->Next = List;
texture->bFirstUpdate = true;
List = probe;
}
//==========================================================================
//
// FCanvasTextureInfo :: UpdateAll
//
// Updates all canvas textures that were visible in the last frame.
//
//==========================================================================
void FCanvasTextureInfo::UpdateAll ()
{
FCanvasTextureInfo *probe;
for (probe = List; probe != NULL; probe = probe->Next)
{
if (probe->Viewpoint != NULL && probe->Texture->bNeedsUpdate)
{
if (currentrenderer == 0) probe->Texture->RenderView (probe->Viewpoint, probe->FOV);
else probe->Texture->RenderGLView (probe->Viewpoint, probe->FOV);
}
}
}
//==========================================================================
//
// FCanvasTextureInfo :: EmptyList
//
// Removes all camera->texture assignments.
//
//==========================================================================
void FCanvasTextureInfo::EmptyList ()
{
FCanvasTextureInfo *probe, *next;
for (probe = List; probe != NULL; probe = next)
{
next = probe->Next;
delete probe;
}
List = NULL;
}
//==========================================================================
//
// FCanvasTextureInfo :: Serialize
//
// Reads or writes the current set of mappings in an archive.
//
//==========================================================================
void FCanvasTextureInfo::Serialize (FArchive &arc)
{
if (arc.IsStoring ())
{
FCanvasTextureInfo *probe;
for (probe = List; probe != NULL; probe = probe->Next)
{
if (probe->Texture != NULL && probe->Viewpoint != NULL)
{
Update to ZDoom r1052: - Fixed: Dead players didn't get the MF_CORPSE flag set. - Fixed: The internal definition of Floor_LowerToNearest had incorrect parameter settings. - Fixed: Heretic's ActivatedTimeBomb had the same spawn ID as the inventory item. - fixed: Heretic's mace did not have its spawn ID set. - For controls that are not bound, the customize controls menu now displays a black --- instead of ???. - Applied Gez's BossBrainPatch3. - Fixed: P_BulletSlope() did not return the linetarget. This effected the Sigil, A_JumpIfCloser, and A_JumpIfTargetInLOS. - Fixed all the new warnings tossed out by GCC 4.3. - Fixed: PickNext/PrevWeapon() did not check for NULL player actors. - Fixed compilation issues with GCC. - Removed special case for nobotnodes in MAPINFO. - Added support for ST's QUARTERGRAVITY flag. - Added a generalized version of Skulltag's A_CheckRailReload function. - Fixed: DrawImage didn't take 0 as a valid image index. - Added Gez's RandomSpawner submission with significant changes. - Added optional blocks for MAPINFO map definitions. ZDoom doesn't use this feature itself but it allows other ports based on ZDoom to implement their own sets of options without making such a MAPINFO unreadable by ZDoom. - Fixed: The mugshot would not reset on re-spawn. - Fixed: Picking up a weapon would sometimes not activate the grin. - Changed: Line_SetIdentification will ignore extended parameters when used in maps defined Hexen style in MAPINFO. - Fixed: Ambient sounds didn't pass their point of origin to S_StartSound. - Fixed: UseType was not properly set for textures defined in TEXTURES. - Fixed: You couldn't set an offset for sprites defined in TEXTURES. - Added read barriers to all actor pointers within player_t except for mo, ReadyWeapon and PendingWeapon. - Added a read barrier to player_t::PrewmorphWeapon. - Fixed: After spawning a deathmatch player P_PlayerStartStomp must be called. - Fixed: SpawnThings must check if the players were spawned before calling P_PlayerStartStomp. - Fixed typo in flat scroll interpolation. - Changed FImageCollection to return translated texture indices so that animated icons can be done with it. - Changed FImageCollection to use a TArray to hold its data. - Fixed: SetChanHeadSettings did an assignment instead of comparing the channel ID witg CHAN_CEILING. - Changed sound sequence names for animated doors to FNames. - Automatically fixed: DCeiling didn't properly serialize its texture id. - Replaced integers as texture ID representation with a specific new type to track down all potentially incorrect uses and remaining WORDs used for texture IDs so that more than 32767 or 65535 textures can be defined. git-svn-id: http://mancubus.net/svn/hosted/gzdoom/trunk@124 b0f79afe-0144-0410-b225-9a4edf0717df
2008-06-28 13:29:59 +00:00
arc << probe->Viewpoint << probe->FOV << probe->PicNum;
}
}
AActor *nullactor = NULL;
arc << nullactor;
}
else
{
AActor *viewpoint;
Update to ZDoom r1052: - Fixed: Dead players didn't get the MF_CORPSE flag set. - Fixed: The internal definition of Floor_LowerToNearest had incorrect parameter settings. - Fixed: Heretic's ActivatedTimeBomb had the same spawn ID as the inventory item. - fixed: Heretic's mace did not have its spawn ID set. - For controls that are not bound, the customize controls menu now displays a black --- instead of ???. - Applied Gez's BossBrainPatch3. - Fixed: P_BulletSlope() did not return the linetarget. This effected the Sigil, A_JumpIfCloser, and A_JumpIfTargetInLOS. - Fixed all the new warnings tossed out by GCC 4.3. - Fixed: PickNext/PrevWeapon() did not check for NULL player actors. - Fixed compilation issues with GCC. - Removed special case for nobotnodes in MAPINFO. - Added support for ST's QUARTERGRAVITY flag. - Added a generalized version of Skulltag's A_CheckRailReload function. - Fixed: DrawImage didn't take 0 as a valid image index. - Added Gez's RandomSpawner submission with significant changes. - Added optional blocks for MAPINFO map definitions. ZDoom doesn't use this feature itself but it allows other ports based on ZDoom to implement their own sets of options without making such a MAPINFO unreadable by ZDoom. - Fixed: The mugshot would not reset on re-spawn. - Fixed: Picking up a weapon would sometimes not activate the grin. - Changed: Line_SetIdentification will ignore extended parameters when used in maps defined Hexen style in MAPINFO. - Fixed: Ambient sounds didn't pass their point of origin to S_StartSound. - Fixed: UseType was not properly set for textures defined in TEXTURES. - Fixed: You couldn't set an offset for sprites defined in TEXTURES. - Added read barriers to all actor pointers within player_t except for mo, ReadyWeapon and PendingWeapon. - Added a read barrier to player_t::PrewmorphWeapon. - Fixed: After spawning a deathmatch player P_PlayerStartStomp must be called. - Fixed: SpawnThings must check if the players were spawned before calling P_PlayerStartStomp. - Fixed typo in flat scroll interpolation. - Changed FImageCollection to return translated texture indices so that animated icons can be done with it. - Changed FImageCollection to use a TArray to hold its data. - Fixed: SetChanHeadSettings did an assignment instead of comparing the channel ID witg CHAN_CEILING. - Changed sound sequence names for animated doors to FNames. - Automatically fixed: DCeiling didn't properly serialize its texture id. - Replaced integers as texture ID representation with a specific new type to track down all potentially incorrect uses and remaining WORDs used for texture IDs so that more than 32767 or 65535 textures can be defined. git-svn-id: http://mancubus.net/svn/hosted/gzdoom/trunk@124 b0f79afe-0144-0410-b225-9a4edf0717df
2008-06-28 13:29:59 +00:00
int fov;
FTextureID picnum;
EmptyList ();
Update to ZDoom r1052: - Fixed: Dead players didn't get the MF_CORPSE flag set. - Fixed: The internal definition of Floor_LowerToNearest had incorrect parameter settings. - Fixed: Heretic's ActivatedTimeBomb had the same spawn ID as the inventory item. - fixed: Heretic's mace did not have its spawn ID set. - For controls that are not bound, the customize controls menu now displays a black --- instead of ???. - Applied Gez's BossBrainPatch3. - Fixed: P_BulletSlope() did not return the linetarget. This effected the Sigil, A_JumpIfCloser, and A_JumpIfTargetInLOS. - Fixed all the new warnings tossed out by GCC 4.3. - Fixed: PickNext/PrevWeapon() did not check for NULL player actors. - Fixed compilation issues with GCC. - Removed special case for nobotnodes in MAPINFO. - Added support for ST's QUARTERGRAVITY flag. - Added a generalized version of Skulltag's A_CheckRailReload function. - Fixed: DrawImage didn't take 0 as a valid image index. - Added Gez's RandomSpawner submission with significant changes. - Added optional blocks for MAPINFO map definitions. ZDoom doesn't use this feature itself but it allows other ports based on ZDoom to implement their own sets of options without making such a MAPINFO unreadable by ZDoom. - Fixed: The mugshot would not reset on re-spawn. - Fixed: Picking up a weapon would sometimes not activate the grin. - Changed: Line_SetIdentification will ignore extended parameters when used in maps defined Hexen style in MAPINFO. - Fixed: Ambient sounds didn't pass their point of origin to S_StartSound. - Fixed: UseType was not properly set for textures defined in TEXTURES. - Fixed: You couldn't set an offset for sprites defined in TEXTURES. - Added read barriers to all actor pointers within player_t except for mo, ReadyWeapon and PendingWeapon. - Added a read barrier to player_t::PrewmorphWeapon. - Fixed: After spawning a deathmatch player P_PlayerStartStomp must be called. - Fixed: SpawnThings must check if the players were spawned before calling P_PlayerStartStomp. - Fixed typo in flat scroll interpolation. - Changed FImageCollection to return translated texture indices so that animated icons can be done with it. - Changed FImageCollection to use a TArray to hold its data. - Fixed: SetChanHeadSettings did an assignment instead of comparing the channel ID witg CHAN_CEILING. - Changed sound sequence names for animated doors to FNames. - Automatically fixed: DCeiling didn't properly serialize its texture id. - Replaced integers as texture ID representation with a specific new type to track down all potentially incorrect uses and remaining WORDs used for texture IDs so that more than 32767 or 65535 textures can be defined. git-svn-id: http://mancubus.net/svn/hosted/gzdoom/trunk@124 b0f79afe-0144-0410-b225-9a4edf0717df
2008-06-28 13:29:59 +00:00
while (arc << viewpoint, viewpoint != NULL)
{
Update to ZDoom r1052: - Fixed: Dead players didn't get the MF_CORPSE flag set. - Fixed: The internal definition of Floor_LowerToNearest had incorrect parameter settings. - Fixed: Heretic's ActivatedTimeBomb had the same spawn ID as the inventory item. - fixed: Heretic's mace did not have its spawn ID set. - For controls that are not bound, the customize controls menu now displays a black --- instead of ???. - Applied Gez's BossBrainPatch3. - Fixed: P_BulletSlope() did not return the linetarget. This effected the Sigil, A_JumpIfCloser, and A_JumpIfTargetInLOS. - Fixed all the new warnings tossed out by GCC 4.3. - Fixed: PickNext/PrevWeapon() did not check for NULL player actors. - Fixed compilation issues with GCC. - Removed special case for nobotnodes in MAPINFO. - Added support for ST's QUARTERGRAVITY flag. - Added a generalized version of Skulltag's A_CheckRailReload function. - Fixed: DrawImage didn't take 0 as a valid image index. - Added Gez's RandomSpawner submission with significant changes. - Added optional blocks for MAPINFO map definitions. ZDoom doesn't use this feature itself but it allows other ports based on ZDoom to implement their own sets of options without making such a MAPINFO unreadable by ZDoom. - Fixed: The mugshot would not reset on re-spawn. - Fixed: Picking up a weapon would sometimes not activate the grin. - Changed: Line_SetIdentification will ignore extended parameters when used in maps defined Hexen style in MAPINFO. - Fixed: Ambient sounds didn't pass their point of origin to S_StartSound. - Fixed: UseType was not properly set for textures defined in TEXTURES. - Fixed: You couldn't set an offset for sprites defined in TEXTURES. - Added read barriers to all actor pointers within player_t except for mo, ReadyWeapon and PendingWeapon. - Added a read barrier to player_t::PrewmorphWeapon. - Fixed: After spawning a deathmatch player P_PlayerStartStomp must be called. - Fixed: SpawnThings must check if the players were spawned before calling P_PlayerStartStomp. - Fixed typo in flat scroll interpolation. - Changed FImageCollection to return translated texture indices so that animated icons can be done with it. - Changed FImageCollection to use a TArray to hold its data. - Fixed: SetChanHeadSettings did an assignment instead of comparing the channel ID witg CHAN_CEILING. - Changed sound sequence names for animated doors to FNames. - Automatically fixed: DCeiling didn't properly serialize its texture id. - Replaced integers as texture ID representation with a specific new type to track down all potentially incorrect uses and remaining WORDs used for texture IDs so that more than 32767 or 65535 textures can be defined. git-svn-id: http://mancubus.net/svn/hosted/gzdoom/trunk@124 b0f79afe-0144-0410-b225-9a4edf0717df
2008-06-28 13:29:59 +00:00
arc << fov << picnum;
Add (viewpoint, picnum, fov);
}
}
}
//==========================================================================
//
// FCanvasTextureInfo :: Mark
//
// Marks all viewpoints in the list for the collector.
//
//==========================================================================
void FCanvasTextureInfo::Mark()
{
for (FCanvasTextureInfo *probe = List; probe != NULL; probe = probe->Next)
{
GC::Mark(probe->Viewpoint);
}
}
//==========================================================================
//
// R_MultiresInit
//
// Called from V_SetResolution()
//
//==========================================================================
void R_MultiresInit ()
{
R_PlaneInitData ();
R_OldBlend = ~0;
}