raze/source/exhumed/src/view.cpp
Christoph Oelckers 847fa48724 - cleaned out the remaining parts of baselayer.h
In particular this means to remove the option to disable widescreen aspect ratios. The way this was handled makes no sense with the current render backend.

The aspect ratio code will have to be redone entirely to properly obey the backend's settings.
2020-08-28 09:06:49 +02:00

513 lines
13 KiB
C++

//-------------------------------------------------------------------------
/*
Copyright (C) 2010-2019 EDuke32 developers and contributors
Copyright (C) 2019 sirlemonhead, Nuke.YKT
This file is part of PCExhumed.
PCExhumed is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License version 2
as published by the Free Software Foundation.
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
//-------------------------------------------------------------------------
#include "ns.h"
#include "compat.h"
#include "engine.h"
#include "names.h"
#include "view.h"
#include "status.h"
#include "exhumed.h"
#include "player.h"
#include "aistuff.h"
#include "sound.h"
#include "mapinfo.h"
#include "v_video.h"
#include "glbackend/glbackend.h"
#include <string.h>
BEGIN_PS_NS
short bSubTitles = true;
int zbob;
fix16_t nDestVertPan[kMaxPlayers] = { 0 };
short dVertPan[kMaxPlayers];
int nCamerax;
int nCameray;
int nCameraz;
short bTouchFloor;
short nQuake[kMaxPlayers] = { 0 };
short nChunkTotal = 0;
fix16_t nCameraa;
fix16_t nCamerapan;
short nViewTop;
short bCamera = false;
int viewz;
short enemy;
short nEnemyPal = 0;
#define MAXINTERPOLATIONS MAXSPRITES
int32_t g_interpolationCnt;
int32_t oldipos[MAXINTERPOLATIONS];
int32_t* curipos[MAXINTERPOLATIONS];
int32_t bakipos[MAXINTERPOLATIONS];
int viewSetInterpolation(int32_t *const posptr)
{
if (g_interpolationCnt >= MAXINTERPOLATIONS)
return 1;
for (bssize_t i = 0; i < g_interpolationCnt; ++i)
if (curipos[i] == posptr)
return 0;
curipos[g_interpolationCnt] = posptr;
oldipos[g_interpolationCnt] = *posptr;
g_interpolationCnt++;
return 0;
}
void viewStopInterpolation(const int32_t * const posptr)
{
for (bssize_t i = 0; i < g_interpolationCnt; ++i)
if (curipos[i] == posptr)
{
g_interpolationCnt--;
oldipos[i] = oldipos[g_interpolationCnt];
bakipos[i] = bakipos[g_interpolationCnt];
curipos[i] = curipos[g_interpolationCnt];
}
}
void viewDoInterpolations(int smoothRatio)
{
int32_t ndelta = 0;
for (bssize_t i = 0, j = 0; i < g_interpolationCnt; ++i)
{
int32_t const odelta = ndelta;
bakipos[i] = *curipos[i];
ndelta = (*curipos[i]) - oldipos[i];
if (odelta != ndelta)
j = mulscale16(ndelta, smoothRatio);
*curipos[i] = oldipos[i] + j;
}
}
void viewUpdateInterpolations(void) //Stick at beginning of G_DoMoveThings
{
for (bssize_t i=g_interpolationCnt-1; i>=0; i--) oldipos[i] = *curipos[i];
}
void viewRestoreInterpolations(void) //Stick at end of drawscreen
{
int32_t i=g_interpolationCnt-1;
for (; i>=0; i--) *curipos[i] = bakipos[i];
}
void InitView()
{
polymostcenterhoriz = 92;
}
// NOTE - not to be confused with Ken's analyzesprites()
static void analyzesprites()
{
short nPlayerSprite = PlayerList[nLocalPlayer].nSprite;
int var_38 = 20;
int var_2C = 30000;
spritetype *pPlayerSprite = &sprite[nPlayerSprite];
besttarget = -1;
int x = pPlayerSprite->x;
int y = pPlayerSprite->y;
int z = pPlayerSprite->z - (GetSpriteHeight(nPlayerSprite) / 2);
short nSector = pPlayerSprite->sectnum;
int nAngle = (2048 - pPlayerSprite->ang) & kAngleMask;
int nTSprite;
tspritetype *pTSprite;
// int var_20 = var_24;
for (nTSprite = spritesortcnt-1, pTSprite = &tsprite[nTSprite]; nTSprite >= 0; nTSprite--, pTSprite--)
{
int nSprite = pTSprite->owner;
spritetype *pSprite = &sprite[nSprite];
if (pTSprite->sectnum >= 0)
{
sectortype *pSector = &sector[pTSprite->sectnum];
int nSectShade = (pSector->ceilingstat & 1) ? pSector->ceilingshade : pSector->floorshade;
int nShade = pTSprite->shade + nSectShade + 6;
pTSprite->shade = clamp(nShade, -128, 127);
}
pTSprite->pal = RemapPLU(pTSprite->pal);
if (pSprite->statnum > 0)
{
runlist_SignalRun(pSprite->lotag - 1, nTSprite | 0x90000);
if ((pSprite->statnum < 150) && (pSprite->cstat & 0x101) && (nSprite != nPlayerSprite))
{
int xval = pSprite->x - x;
int yval = pSprite->y - y;
int vcos = Cos(nAngle);
int vsin = Sin(nAngle);
int edx = ((vcos * yval) + (xval * vsin)) >> 14;
int ebx = klabs(((vcos * xval) - (yval * vsin)) >> 14);
if (!ebx)
continue;
edx = (klabs(edx) * 32) / ebx;
if (ebx < 1000 && ebx < var_2C && edx < 10)
{
besttarget = nSprite;
var_38 = edx;
var_2C = ebx;
}
else if (ebx < 30000)
{
int t = var_38 - edx;
if (t > 3 || (ebx < var_2C && klabs(t) < 5))
{
var_38 = edx;
var_2C = ebx;
besttarget = nSprite;
}
}
}
}
}
if (besttarget != -1)
{
spritetype *pTarget = &sprite[besttarget];
nCreepyTimer = kCreepyCount;
if (!cansee(x, y, z, nSector, pTarget->x, pTarget->y, pTarget->z - GetSpriteHeight(besttarget), pTarget->sectnum))
{
besttarget = -1;
}
}
}
void ResetView()
{
EraseScreen(overscanindex);
#ifdef USE_OPENGL
videoTintBlood(0, 0, 0);
#endif
}
static inline int interpolate16(int a, int b, int smooth)
{
return a + mulscale16(b - a, smooth);
}
static TextOverlay subtitleOverlay;
void DrawView(double smoothRatio, bool sceneonly)
{
int playerX;
int playerY;
int playerZ;
short nSector;
fix16_t nAngle;
fix16_t pan;
zbob = Sin(2 * bobangle) >> 3;
int nPlayerSprite = PlayerList[nLocalPlayer].nSprite;
int nPlayerOldCstat = sprite[nPlayerSprite].cstat;
int nDoppleOldCstat = sprite[nDoppleSprite[nLocalPlayer]].cstat;
if (nSnakeCam >= 0 && !sceneonly)
{
int nSprite = SnakeList[nSnakeCam].nSprites[0];
playerX = sprite[nSprite].x;
playerY = sprite[nSprite].y;
playerZ = sprite[nSprite].z;
nSector = sprite[nSprite].sectnum;
nAngle = fix16_from_int(sprite[nSprite].ang);
SetGreenPal();
enemy = SnakeList[nSnakeCam].nEnemy;
if (enemy <= -1 || totalmoves & 1)
{
nEnemyPal = -1;
}
else
{
nEnemyPal = sprite[enemy].pal;
sprite[enemy].pal = 5;
}
}
else
{
playerX = interpolate16(PlayerList[nLocalPlayer].opos.x, sprite[nPlayerSprite].x, smoothRatio);
playerY = interpolate16(PlayerList[nLocalPlayer].opos.y, sprite[nPlayerSprite].y, smoothRatio);
playerZ = interpolate16(PlayerList[nLocalPlayer].opos.z, sprite[nPlayerSprite].z, smoothRatio)
+ interpolate16(oeyelevel[nLocalPlayer], eyelevel[nLocalPlayer], smoothRatio);
nSector = nPlayerViewSect[nLocalPlayer];
nAngle = PlayerList[nLocalPlayer].q16angle;
if (!bCamera)
{
sprite[nPlayerSprite].cstat |= CSTAT_SPRITE_INVISIBLE;
sprite[nDoppleSprite[nLocalPlayer]].cstat |= CSTAT_SPRITE_INVISIBLE;
}
}
nCameraa = nAngle;
if (!bCamera || nFreeze || sceneonly)
{
if (nSnakeCam >= 0 && !sceneonly)
{
pan = F16(92);
viewz = playerZ;
}
else
{
viewz = playerZ + nQuake[nLocalPlayer];
int floorZ = sector[sprite[nPlayerSprite].sectnum].floorz;
pan = PlayerList[nLocalPlayer].q16horiz;
if (viewz > floorZ)
viewz = floorZ;
nCameraa += fix16_from_int((nQuake[nLocalPlayer] >> 7) % 31);
nCameraa &= 0x7FFFFFF;
}
}
else
{
clipmove_old((int32_t*)&playerX, (int32_t*)&playerY, (int32_t*)&playerZ, &nSector,
-2000 * Sin(inita + 512),
-2000 * Sin(inita),
4, 0, 0, CLIPMASK1);
pan = F16(92);
viewz = playerZ;
}
nCamerax = playerX;
nCameray = playerY;
nCameraz = playerZ;
int Z = sector[nSector].ceilingz + 256;
if (Z <= viewz)
{
Z = sector[nSector].floorz - 256;
if (Z < viewz)
viewz = Z;
}
else {
viewz = Z;
}
nCamerapan = pan;
if (nFreeze == 2 || nFreeze == 1)
{
nSnakeCam = -1;
videoSetViewableArea(0, 0, xdim - 1, ydim - 1);
}
UpdateMap();
if (nFreeze != 3)
{
static uint8_t sectorFloorPal[MAXSECTORS];
static uint8_t sectorCeilingPal[MAXSECTORS];
static uint8_t wallPal[MAXWALLS];
int const viewingRange = viewingrange;
int const vr = Blrintf(65536.f * tanf(r_fov * (fPI / 360.f)));
videoSetCorrectedAspect();
renderSetAspect(mulscale16(vr, viewingrange), yxaspect);
if (HavePLURemap())
{
for (int i = 0; i < numsectors; i++)
{
sectorFloorPal[i] = sector[i].floorpal;
sectorCeilingPal[i] = sector[i].ceilingpal;
sector[i].floorpal = RemapPLU(sectorFloorPal[i]);
sector[i].ceilingpal = RemapPLU(sectorCeilingPal[i]);
}
for (int i = 0; i < numwalls; i++)
{
wallPal[i] = wall[i].pal;
wall[i].pal = RemapPLU(wallPal[i]);
}
}
renderDrawRoomsQ16(nCamerax, nCameray, viewz, nCameraa, nCamerapan, nSector);
analyzesprites();
renderDrawMasks();
if (HavePLURemap())
{
for (int i = 0; i < numsectors; i++)
{
sector[i].floorpal = sectorFloorPal[i];
sector[i].ceilingpal = sectorCeilingPal[i];
}
for (int i = 0; i < numwalls; i++)
{
wall[i].pal = wallPal[i];
}
}
renderSetAspect(viewingRange, divscale16(ydim * 8, xdim * 5));
if (nFreeze)
{
nSnakeCam = -1;
if (nFreeze == 2)
{
if (nHeadStage == 4)
{
nHeadStage = 5;
sprite[nPlayerSprite].cstat |= 0x8000;
int ang2 = fix16_to_int(nCameraa) - sprite[nPlayerSprite].ang;
if (ang2 < 0)
ang2 = -ang2;
if (ang2 > 10)
{
inita -= (ang2 >> 3);
return;
}
if (bSubTitles)
{
subtitleOverlay.Start(gameclock);
if (currentLevel->levelNumber == 1)
subtitleOverlay.ReadyCinemaText(0);
else
subtitleOverlay.ReadyCinemaText(4);
}
inputState.ClearAllInput();
}
else if (nHeadStage == 5)
{
if ((bSubTitles && !subtitleOverlay.AdvanceCinemaText(gameclock)) || inputState.CheckAllInput())
{
inputState.ClearAllInput();
EndLevel = 2;
if (CDplaying()) {
fadecdaudio();
}
}
else subtitleOverlay.DisplayText();
}
}
}
else if (!sceneonly)
{
if (nSnakeCam < 0)
{
DrawWeapons(smoothRatio);
DrawMap();
}
else
{
RestoreGreenPal();
if (nEnemyPal > -1) {
sprite[enemy].pal = nEnemyPal;
}
DrawMap();
}
}
}
else
{
twod->ClearScreen();
}
sprite[nPlayerSprite].cstat = nPlayerOldCstat;
sprite[nDoppleSprite[nLocalPlayer]].cstat = nDoppleOldCstat;
flash = 0;
}
bool GameInterface::GenerateSavePic()
{
DrawView(65536, true);
return true;
}
void NoClip()
{
}
void Clip()
{
}
static SavegameHelper sgh("view",
SV(nCamerax),
SV(nCameray),
SV(nCameraz),
SV(bTouchFloor),
SV(nChunkTotal),
SV(nCameraa),
SV(nCamerapan),
SV(bCamera),
SV(viewz),
SV(enemy),
SV(nEnemyPal),
SA(nDestVertPan),
SA(dVertPan),
SA(nQuake),
SV(g_interpolationCnt),
SA(oldipos),
SA(curipos),
SA(bakipos),
nullptr);
END_PS_NS