- render camera textures with the hardware renderer.

This removes the last active use case for the software renderer and allows rendering the camera views at a higher resolution.
For Shadow Warrior this necessitated a split of JS_DrawMirrors, because it processed cameras and mirrors in the same loop which cannot be done with the hardware renderer.
This commit is contained in:
Christoph Oelckers 2020-03-29 14:01:46 +02:00
parent 8f3cc0b5af
commit 621a9338e5
17 changed files with 320 additions and 324 deletions

View file

@ -838,8 +838,6 @@ int32_t qloadkvx(int32_t voxindex, const char *filename);
void vox_undefine(int32_t const);
void vox_deinit();
void squarerotatetile(int16_t tilenume);
int32_t videoSetGameMode(char davidoption, int32_t daupscaledxdim, int32_t daupscaledydim, int32_t dabpp, int32_t daupscalefactor);
void videoNextPage(void);
void videoSetCorrectedAspect();
@ -849,7 +847,7 @@ inline void renderFlushPerms(void) {}
void plotpixel(int32_t x, int32_t y, char col);
void renderSetTarget(int16_t tilenume, int32_t xsiz, int32_t ysiz);
void renderRestoreTarget(void);
void renderRestoreTarget();
void renderPrepareMirror(int32_t dax, int32_t day, int32_t daz, fix16_t daang, fix16_t dahoriz, int16_t dawall,
int32_t *tposx, int32_t *tposy, fix16_t *tang);
void renderCompleteMirror(void);

View file

@ -8,6 +8,7 @@
#define engine_c_
#include "gl_load.h"
#include "a.h"
#include "baselayer.h"
#include "build.h"
@ -36,6 +37,7 @@
# include "polymost.h"
#include "v_video.h"
#include "../../glbackend/glbackend.h"
#include "gl_renderer.h"
#endif
//////////
@ -1323,14 +1325,6 @@ static int32_t mirrorsx1, mirrorsy1, mirrorsx2, mirrorsy2;
#define MAXSETVIEW 4
static int32_t setviewcnt = 0; // interface layers use this now
static intptr_t bakframeplace[MAXSETVIEW];
static int32_t bakxsiz[MAXSETVIEW], bakysiz[MAXSETVIEW];
static vec2_t bakwindowxy1[MAXSETVIEW], bakwindowxy2[MAXSETVIEW];
#ifdef USE_OPENGL
static int32_t bakrendmode;
#endif
static int32_t baktile;
#ifdef GAMENAME
char apptitle[256] = GAMENAME;
@ -10087,44 +10081,35 @@ void videoClearScreen(int32_t dacol)
//MUST USE RESTOREFORDRAWROOMS AFTER DRAWING
static int32_t setviewcnt = 0; // interface layers use this now
static int32_t bakxsiz, bakysiz;
static vec2_t bakwindowxy1, bakwindowxy2;
//
// setviewtotile
//
void renderSetTarget(int16_t tilenume, int32_t xsiz, int32_t ysiz)
{
if (setviewcnt >= MAXSETVIEW-1)
if (setviewcnt > 0)
return;
if (xsiz <= 0 ||
ysiz <= 0)
return;
OpenGLRenderer::GLRenderer->StartOffscreen();
OpenGLRenderer::GLRenderer->BindToFrameBuffer(TileFiles.tiles[tilenume]);
//DRAWROOMS TO TILE BACKUP&SET CODE
TileFiles.tileCreate(tilenume, xsiz, ysiz);
bakxsiz[setviewcnt] = xdim; bakysiz[setviewcnt] = ydim;
bakframeplace[setviewcnt] = frameplace; frameplace = (intptr_t)tilePtr(tilenume);
bakwindowxy1[setviewcnt] = windowxy1;
bakwindowxy2[setviewcnt] = windowxy2;
bakxsiz = xdim; bakysiz = ydim;
bakwindowxy1 = windowxy1;
bakwindowxy2 = windowxy2;
if (setviewcnt == 0)
{
#ifdef USE_OPENGL
bakrendmode = rendmode;
#endif
baktile = tilenume;
}
#ifdef USE_OPENGL
rendmode = REND_CLASSIC;
#endif
copybufbyte(&startumost[windowxy1.x],&bakumost[windowxy1.x],(windowxy2.x-windowxy1.x+1)*sizeof(bakumost[0]));
copybufbyte(&startdmost[windowxy1.x],&bakdmost[windowxy1.x],(windowxy2.x-windowxy1.x+1)*sizeof(bakdmost[0]));
setviewcnt++;
offscreenrendering = 1;
xdim = ysiz;
ydim = xsiz;
videoSetViewableArea(0,0,ysiz-1,xsiz-1);
xdim = ysiz*4;
ydim = xsiz*4;
videoSetViewableArea(0,0,ysiz*4-1,xsiz*4-1);
renderSetAspect(65536,65536);
calc_ylookup(ysiz, xsiz);
@ -10134,73 +10119,26 @@ void renderSetTarget(int16_t tilenume, int32_t xsiz, int32_t ysiz)
//
// setviewback
//
void renderRestoreTarget(void)
void renderRestoreTarget()
{
if (setviewcnt <= 0) return;
setviewcnt--;
offscreenrendering = (setviewcnt>0);
#ifdef USE_OPENGL
if (setviewcnt == 0)
{
rendmode = bakrendmode;
tileInvalidate(baktile,-1,-1);
}
#endif
OpenGLRenderer::GLRenderer->EndOffscreen();
xdim = bakxsiz[setviewcnt];
ydim = bakysiz[setviewcnt];
videoSetViewableArea(bakwindowxy1[setviewcnt].x,bakwindowxy1[setviewcnt].y,
bakwindowxy2[setviewcnt].x,bakwindowxy2[setviewcnt].y);
copybufbyte(&bakumost[windowxy1.x],&startumost[windowxy1.x],(windowxy2.x-windowxy1.x+1)*sizeof(startumost[0]));
copybufbyte(&bakdmost[windowxy1.x],&startdmost[windowxy1.x],(windowxy2.x-windowxy1.x+1)*sizeof(startdmost[0]));
frameplace = bakframeplace[setviewcnt];
xdim = bakxsiz;
ydim = bakysiz;
videoSetViewableArea(bakwindowxy1.x,bakwindowxy1.y,
bakwindowxy2.x,bakwindowxy2.y);
calc_ylookup((setviewcnt == 0) ? bytesperline : bakxsiz[setviewcnt],
bakysiz[setviewcnt]);
calc_ylookup((setviewcnt == 0) ? bytesperline : bakxsiz,
bakysiz);
modechange=1;
}
//
// squarerotatetile
//
void squarerotatetile(int16_t tilenume)
{
int const siz = tilesiz[tilenume].x;
if (siz != tilesiz[tilenume].y)
return;
uint8_t *ptr1, *ptr2;
auto p = tileData(tilenume);
if (!p) return; // safety precaution, this may only be called on writable tiles for camera textures.
for (bssize_t i=siz-1, j; i>=3; i-=4)
{
ptr2 = ptr1 = (p+i*(siz+1));
swapchar(--ptr1, (ptr2 -= siz));
for (j=(i>>1)-1; j>=0; --j)
swapchar2((ptr1 -= 2), (ptr2 -= (siz<<1)), siz);
ptr2 = ptr1 = (p+(i-1)*(siz+1));
for (j=((i-1)>>1)-1; j>=0; --j)
swapchar2((ptr1 -= 2), (ptr2 -= (siz<<1)), siz);
ptr2 = ptr1 = (p+(i-2)*(siz+1));
swapchar(--ptr1, (ptr2 -= siz));
for (j=((i-2)>>1)-1; j>=0; --j)
swapchar2((ptr1 -= 2), (ptr2 -= (siz<<1)), siz);
ptr2 = ptr1 = (p+(i-3)*(siz+1));
for (j=((i-3)>>1)-1; j>=0; --j)
swapchar2((ptr1 -= 2), (ptr2 -= (siz<<1)), siz);
}
}
//
// preparemirror
//

View file

@ -541,10 +541,20 @@ static void polymost_drawpoly(vec2f_t const * const dpxy, int32_t const n, int32
{
float const r = 1.f / dd[i];
if (TileFiles.tiles[globalpicnum]->GetUseType() == FTexture::Canvas)
{
//update texcoords, canvas textures are upside down!
vt->SetTexCoord(
uu[i] * r * scale.x - usub,
1.f - (vv[i] * r * scale.y - vsub));
}
else
{
//update texcoords
vt->SetTexCoord(
uu[i] * r * scale.x - usub,
vv[i] * r * scale.y - vsub);
}
//update verts
vt->SetVertex(

View file

@ -177,9 +177,11 @@ void FGLRenderer::BindToFrameBuffer(FTexture *mat)
if (BaseLayer == nullptr)
{
// must create the hardware texture first
BaseLayer->CreateTexture(mat->GetWidth(), mat->GetHeight(), FHardwareTexture::TrueColor, false);
BaseLayer = new FHardwareTexture();
BaseLayer->CreateTexture(mat->GetWidth()*4, mat->GetHeight()*4, FHardwareTexture::TrueColor, false);
mat->SetHardwareTexture(0, BaseLayer);
}
BaseLayer->BindToFrameBuffer(mat->GetWidth(), mat->GetHeight());
BaseLayer->BindToFrameBuffer(mat->GetWidth()*4, mat->GetHeight()*4);
}
//===========================================================================

View file

@ -254,6 +254,11 @@ void BuildTiles::ClearTextureCache(bool artonly)
}
}
//===========================================================================
//
// InvalidateTile
//
//===========================================================================
void BuildTiles::InvalidateTile(int num)
{
@ -271,6 +276,21 @@ void BuildTiles::InvalidateTile(int num)
}
}
//===========================================================================
//
// MakeCanvas
//
// Turns texture into a canvas (i.e. camera texture)
//
//===========================================================================
void BuildTiles::MakeCanvas(int tilenum, int width, int height)
{
auto canvas = ValidateCustomTile(tilenum, FTexture::Canvas);
canvas->Size.x = width;
canvas->Size.y = height;
}
//===========================================================================
//
// LoadArtFile
@ -388,6 +408,10 @@ FTexture* BuildTiles::ValidateCustomTile(int tilenum, int type)
// todo: invalidate hardware textures for tile.
replacement = new FRestorableTile(tile);
}
else if (type == FTexture::Canvas)
{
replacement = new FCanvasTexture("camera", 0, 0);
}
else return nullptr;
AddTile(tilenum, replacement);
return replacement;
@ -683,7 +707,6 @@ int BuildTiles::tileCreateRotated(int tileNum)
auto src = buffer.Data();
auto dst = dbuffer.Data();
// the engine has a squarerotatetile() we could call, but it mirrors at the same time
auto siz = tex->GetSize();
for (int x = 0; x < siz.x; ++x)
{

View file

@ -201,6 +201,7 @@ public:
Art, // from an ART file, readonly
Writable, // A writable texture
Restorable, // a writable copy of something else
Canvas, // camera texture
User // A texture with user-provided image content
};
@ -311,6 +312,33 @@ protected:
friend struct BuildTiles;
};
class FCanvasTexture : public FTexture
{
public:
FCanvasTexture(const char* name, int width, int height)
{
Name = name;
Size.x = width;
Size.y = height;
bMasked = false;
bTranslucent = false;
//bNoExpand = true;
useType = FTexture::Canvas;
}
void NeedUpdate() { bNeedsUpdate = true; }
void SetUpdated(bool rendertype) { bNeedsUpdate = false; bFirstUpdate = false; bLastUpdateType = rendertype; }
protected:
bool bLastUpdateType = false;
bool bNeedsUpdate = true;
public:
bool bFirstUpdate = true;
friend struct FCanvasTextureInfo;
};
class FTileTexture : public FTexture
{
public:
@ -551,6 +579,7 @@ struct BuildTiles
int tileCreateRotated(int owner);
void ClearTextureCache(bool artonly = false);
void InvalidateTile(int num);
void MakeCanvas(int tilenum, int width, int height);
};
int tileGetCRC32(int tileNum);

View file

@ -3547,8 +3547,7 @@ void G_DoSpriteAnimations(int32_t ourx, int32_t oury, int32_t ourz, int32_t oura
case VIEWSCREEN__STATIC:
case VIEWSCREEN2__STATIC:
{
int const viewscrShift = G_GetViewscreenSizeShift(t);
int const viewscrTile = TILE_VIEWSCR-viewscrShift;
int const viewscrTile = TILE_VIEWSCR;
if (g_curViewscreen >= 0 && actor[OW(i)].t_data[0] == 1)
{
@ -3559,25 +3558,7 @@ void G_DoSpriteAnimations(int32_t ourx, int32_t oury, int32_t ourz, int32_t oura
}
else if (g_curViewscreen == i && display_mirror != 3 && tileData(viewscrTile))
{
// this exposes a sprite sorting issue which needs to be debugged further...
#if 0
if (spritesortcnt < maxspritesonscreen)
{
auto const newt = &tsprite[spritesortcnt++];
*newt = *t;
newt->cstat |= 2|512;
newt->x += (sintable[(newt->ang+512)&2047]>>12);
newt->y += (sintable[newt->ang&2047]>>12);
updatesector(newt->x, newt->y, &newt->sectnum);
}
#endif
t->picnum = viewscrTile;
#if VIEWSCREENFACTOR > 0
t->xrepeat >>= viewscrShift;
t->yrepeat >>= viewscrShift;
#endif
}
break;

View file

@ -43,8 +43,6 @@ BEGIN_DUKE_NS
// Compile game-side legacy Room over Room code?
#define LEGACY_ROR 1
# define VIEWSCREENFACTOR 2
enum GametypeFlags_t {
GAMETYPE_COOP = 0x00000001,
GAMETYPE_WEAPSTAY = 0x00000002,
@ -437,32 +435,6 @@ static inline int G_GetMusicIdx(const char *str)
#endif
#ifndef ONLY_USERDEFS
template <typename T>
static inline int G_GetViewscreenSizeShift(T const * spr)
{
#if VIEWSCREENFACTOR == 0
UNREFERENCED_PARAMETER(spr);
return VIEWSCREENFACTOR;
#else
static CONSTEXPR int const mask = (1<<VIEWSCREENFACTOR)-1;
const int rem = (spr->xrepeat & mask) | (spr->yrepeat & mask);
for (int i=0; i < VIEWSCREENFACTOR; i++)
if (rem & (1<<i))
return i;
return VIEWSCREENFACTOR;
#endif
}
#if defined game_c_ || !defined DISABLE_INLINING
#endif
#endif
END_DUKE_NS
#endif

View file

@ -414,8 +414,6 @@ static void G_SetupCamTile(int spriteNum, int tileNum, int smoothRatio)
finishTileSetup:
renderRestoreTarget();
squarerotatetile(tileNum);
tileInvalidate(tileNum, -1, 255);
}
void G_AnimateCamSprite(int smoothRatio)
@ -438,11 +436,8 @@ void G_AnimateCamSprite(int smoothRatio)
if (OW(spriteNum) >= 0 && dist(&sprite[pPlayer->i], &sprite[spriteNum]) < VIEWSCREEN_ACTIVE_DISTANCE)
{
int const viewscrShift = G_GetViewscreenSizeShift((uspriteptr_t)&sprite[spriteNum]);
int const viewscrTile = TILE_VIEWSCR - viewscrShift;
if (tileData(viewscrTile) ==nullptr)
TileFiles.tileCreate(viewscrTile, tilesiz[PN(spriteNum)].x << viewscrShift, tilesiz[PN(spriteNum)].y << viewscrShift);
int const viewscrTile = TILE_VIEWSCR;
TileFiles.MakeCanvas(viewscrTile, tilesiz[PN(spriteNum)].x, tilesiz[PN(spriteNum)].y);
G_SetupCamTile(OW(spriteNum), viewscrTile, smoothRatio);
#ifdef POLYMER

View file

@ -134,11 +134,13 @@ FHardwareTexture* GLInstance::LoadTexture(FTexture* tex, int textype, int palid)
auto phwtex = tex->GetHardwareTexture(palid);
if (phwtex) return *phwtex;
FHardwareTexture *hwtex;
FHardwareTexture *hwtex = nullptr;
if (textype == TT_INDEXED)
hwtex = CreateIndexedTexture(tex);
else
else if (tex->GetUseType() != FTexture::Canvas)
hwtex = CreateTrueColorTexture(tex, textype == TT_HICREPLACE? -1 : palid, textype == TT_BRIGHTMAP, textype == TT_BRIGHTMAP);
else
hwtex = nullptr;
if (hwtex) tex->SetHardwareTexture(palid, hwtex);
return hwtex;
@ -169,8 +171,9 @@ bool GLInstance::SetTextureInternal(int picnum, FTexture* tex, int palette, int
auto& h = hictinting[palette];
bool applytint = false;
// Canvas textures must be treated like hightile replacements in the following code.
auto rep = (hw_hightile && !(h.f & HICTINT_ALWAYSUSEART)) ? tex->FindReplacement(palette) : nullptr;
if (rep)
if (rep || tex->GetUseType() == FTexture::Canvas)
{
if (usepalette != 0)
{
@ -180,9 +183,12 @@ bool GLInstance::SetTextureInternal(int picnum, FTexture* tex, int palette, int
GLInterface.SetBasepalTint(hh.tint);
}
if (rep)
{
tex = rep->faces[0];
}
if (!rep || rep->palnum != palette || (h.f & HICTINT_APPLYOVERALTPAL)) applytint = true;
TextureType = TT_HICREPLACE;
if (rep->palnum != palette || (h.f & HICTINT_APPLYOVERALTPAL)) applytint = true;
}
else
{

View file

@ -1262,22 +1262,6 @@ void G_DrawRooms(int32_t playerNum, int32_t smoothRatio)
renderDrawMasks();
#endif
screen->FinishScene();
if (g_screenCapture)
{
g_screenCapture = 0;
tileInvalidate(TILE_SAVESHOT, 0, 255);
//if (videoGetRenderMode() == REND_CLASSIC)
{
renderRestoreTarget();
}
#ifdef USE_OPENGL
//else
// G_ReadGLFrame();
#endif
}
}
G_RestoreInterpolations();
@ -4808,8 +4792,7 @@ default_case1:
case VIEWSCREEN2__STATIC:
{
if (RR) goto default_case2;
int const viewscrShift = G_GetViewscreenSizeShift(t);
int const viewscrTile = TILE_VIEWSCR-viewscrShift;
int const viewscrTile = TILE_VIEWSCR;
if (g_curViewscreen >= 0 && actor[OW(i)].t_data[0] == 1)
{
@ -4818,27 +4801,11 @@ default_case1:
t->xrepeat += 10;
t->yrepeat += 9;
}
else if (g_curViewscreen == i && display_mirror != 3 && tileData(viewscrTile))
else if (g_curViewscreen == i && display_mirror != 3)
{
// this exposes a sprite sorting issue which needs to be debugged further...
#if 0
if (spritesortcnt < maxspritesonscreen)
{
auto const newt = &tsprite[spritesortcnt++];
*newt = *t;
newt->cstat |= 2|512;
newt->x += (sintable[(newt->ang+512)&2047]>>12);
newt->y += (sintable[newt->ang&2047]>>12);
updatesector(newt->x, newt->y, &newt->sectnum);
}
#endif
t->picnum = viewscrTile;
#if VIEWSCREENFACTOR > 0
t->xrepeat >>= viewscrShift;
t->yrepeat >>= viewscrShift;
#endif
}
break;

View file

@ -40,8 +40,6 @@ BEGIN_RR_NS
// Compile game-side legacy Room over Room code?
#define LEGACY_ROR 1
# define VIEWSCREENFACTOR 2
enum GametypeFlags_t {
GAMETYPE_COOP = 0x00000001,
GAMETYPE_WEAPSTAY = 0x00000002,
@ -426,24 +424,6 @@ static inline int G_GetMusicIdx(const char *str)
extern void G_PrintCurrentMusic(void);
template <typename T>
static inline int G_GetViewscreenSizeShift(T const *tspr)
{
#if VIEWSCREENFACTOR == 0
UNREFERENCED_PARAMETER(tspr);
return VIEWSCREENFACTOR;
#else
static const int mask = (1<<VIEWSCREENFACTOR)-1;
const int rem = (tspr->xrepeat & mask) | (tspr->yrepeat & mask);
for (bssize_t i=0; i < VIEWSCREENFACTOR; i++)
if (rem & (1<<i))
return i;
return VIEWSCREENFACTOR;
#endif
}
#endif

View file

@ -245,7 +245,6 @@ G_EXTERN input_t inputfifo[MOVEFIFOSIZ][MAXPLAYERS];
G_EXTERN int32_t g_noEnemies;
G_EXTERN int32_t g_restorePalette;
G_EXTERN int32_t g_screenCapture;
G_EXTERN uint32_t everyothertime;
G_EXTERN uint32_t g_moveThingsCount;
G_EXTERN double g_gameUpdateTime;

View file

@ -519,8 +519,6 @@ static void G_SetupCamTile(int spriteNum, int tileNum, int smoothRatio)
screen->FinishScene();
renderRestoreTarget();
squarerotatetile(tileNum);
tileInvalidate(tileNum, -1, 255);
}
void G_AnimateCamSprite(int smoothRatio)
@ -543,11 +541,8 @@ void G_AnimateCamSprite(int smoothRatio)
if (OW(spriteNum) >= 0 && dist(&sprite[pPlayer->i], &sprite[spriteNum]) < VIEWSCREEN_ACTIVE_DISTANCE)
{
int const viewscrShift = G_GetViewscreenSizeShift((const uspritetype *)&sprite[spriteNum]);
int const viewscrTile = TILE_VIEWSCR - viewscrShift;
if (tileData(viewscrTile) == nullptr)
TileFiles.tileCreate(viewscrTile, tilesiz[PN(spriteNum)].x << viewscrShift, tilesiz[PN(spriteNum)].y << viewscrShift);
int const viewscrTile = TILE_VIEWSCR;
TileFiles.MakeCanvas(viewscrTile, tilesiz[PN(spriteNum)].x, tilesiz[PN(spriteNum)].y);
G_SetupCamTile(OW(spriteNum), viewscrTile, smoothRatio);
#ifdef POLYMER

View file

@ -2114,6 +2114,12 @@ drawscreen(PLAYERp pp)
if (FAF_DebugView)
videoClearViewableArea(255L);
if (dimensionmode != 6)// && !ScreenSavePic)
{
// Cameras must be done before the main loop.
JS_DrawCameras(pp, tx, ty, tz, tang, thoriz);
}
screen->BeginScene();
OverlapDraw = TRUE;
DrawOverlapRoom(tx, ty, tz, tang, thoriz, tsectnum);

View file

@ -57,8 +57,6 @@ short mirrorcnt; //, floormirrorcnt;
//short floormirrorsector[MAXMIRRORS];
SWBOOL mirrorinview;
SWBOOL MirrorMoveSkip16 = 0;
// Voxel stuff
//SWBOOL bVoxelsOn = TRUE; // Turn voxels on by default
SWBOOL bSpinBobVoxels = FALSE; // Do twizzly stuff to voxels, but
@ -464,7 +462,7 @@ void JS_InitMirrors(void)
void drawroomstotile(int daposx, int daposy, int daposz,
short daang, int dahoriz, short dacursectnum, short tilenume)
{
TileFiles.tileCreate(tilenume, tilesiz[tilenume].x, tilesiz[tilenume].y);
TileFiles.MakeCanvas(tilenume, tilesiz[tilenume].x, tilesiz[tilenume].y);
renderSetTarget(tilenume, tilesiz[tilenume].x, tilesiz[tilenume].y);
screen->BeginScene();
@ -475,10 +473,6 @@ void drawroomstotile(int daposx, int daposy, int daposz,
screen->FinishScene();
renderRestoreTarget();
squarerotatetile(tilenume);
tileInvalidate(tilenume, -1, -1);
}
void
@ -527,8 +521,10 @@ int camloopcnt = 0; // Timer to cycle through player
// views
short camplayerview = 1; // Don't show yourself!
void
JS_DrawMirrors(PLAYERp pp, int tx, int ty, int tz, short tpang, int tphoriz)
// Hack job alert!
// Mirrors and cameras are maintained in the same data structure, but for hardware rendering they cannot be interleaved.
// So this function replicates JS_DrawMirrors to only process the camera textures but not change any global state.
void JS_DrawCameras(PLAYERp pp, int tx, int ty, int tz, short tpang, int tphoriz)
{
int j, cnt;
int dist;
@ -540,8 +536,6 @@ JS_DrawMirrors(PLAYERp pp, int tx, int ty, int tz, short tpang, int tphoriz)
// drift!
SWBOOL bIsWallMirror = FALSE;
MirrorMoveSkip16 = (MirrorMoveSkip16 + 1) & 15;
camloopcnt += (int32_t)(totalclock - ototalclock);
if (camloopcnt > (60 * 5)) // 5 seconds per player view
{
@ -551,6 +545,190 @@ JS_DrawMirrors(PLAYERp pp, int tx, int ty, int tz, short tpang, int tphoriz)
camplayerview = 1;
}
// WARNING! Assuming (MIRRORLABEL&31) = 0 and MAXMIRRORS = 64 <-- JBF: wrong
longptr = (int*)&gotpic[MIRRORLABEL >> 3];
if (longptr && (longptr[0] || longptr[1]))
{
for (cnt = MAXMIRRORS - 1; cnt >= 0; cnt--)
{
if (!mirror[cnt].ismagic) continue; // these are definitely not camera textures.
//if (TEST_GOTPIC(cnt + MIRRORLABEL) || TEST_GOTPIC(cnt + CAMSPRITE))
if (TEST_GOTPIC(cnt + MIRRORLABEL) || ((unsigned)mirror[cnt].campic < MAXTILES && TEST_GOTPIC(mirror[cnt].campic)))
{
// Do not change any global state here!
bIsWallMirror = (TEST_GOTPIC(cnt + MIRRORLABEL));
dist = 0x7fffffff;
if (bIsWallMirror)
{
j = klabs(wall[mirror[cnt].mirrorwall].x - tx);
j += klabs(wall[mirror[cnt].mirrorwall].y - ty);
if (j < dist)
dist = j;
}
else
{
SPRITEp tp;
tp = &sprite[mirror[cnt].camsprite];
j = klabs(tp->x - tx);
j += klabs(tp->y - ty);
if (j < dist)
dist = j;
}
SPRITEp sp = NULL;
int camhoriz;
short w;
int dx, dy, dz, tdx, tdy, tdz, midx, midy;
ASSERT(mirror[cnt].camera != -1);
sp = &sprite[mirror[cnt].camera];
ASSERT(sp);
// Calculate the angle of the mirror wall
w = mirror[cnt].mirrorwall;
// Get wall midpoint for offset in mirror view
midx = (wall[w].x + wall[wall[w].point2].x) / 2;
midy = (wall[w].y + wall[wall[w].point2].y) / 2;
// Finish finding offsets
tdx = klabs(midx - tx);
tdy = klabs(midy - ty);
if (midx >= tx)
dx = sp->x - tdx;
else
dx = sp->x + tdx;
if (midy >= ty)
dy = sp->y - tdy;
else
dy = sp->y + tdy;
tdz = klabs(tz - sp->z);
if (tz >= sp->z)
dz = sp->z + tdz;
else
dz = sp->z - tdz;
// Is it a TV cam or a teleporter that shows destination?
// TRUE = It's a TV cam
mirror[cnt].mstate = m_normal;
if (TEST_BOOL1(sp))
mirror[cnt].mstate = m_viewon;
// Show teleport destination
// NOTE: Adding MAXSECTORS lets you draw a room, even if
// you are outside of it!
if (mirror[cnt].mstate == m_viewon)
{
SWBOOL DoCam = FALSE;
if (mirror[cnt].campic == -1)
{
Printf("Missing campic for mirror %d. Map Coordinates: x = %d, y = %d\n", cnt, midx, midy);
return;
}
// BOOL2 = Oscilate camera
if (TEST_BOOL2(sp) && MoveSkip2 == 0)
{
if (TEST_BOOL3(sp)) // If true add increment to
// angle else subtract
{
// Store current angle in TAG5
SP_TAG5(sp) = NORM_ANGLE((SP_TAG5(sp) + 4));
// TAG6 = Turn radius
if (klabs(GetDeltaAngle(SP_TAG5(sp), sp->ang)) >= SP_TAG6(sp))
{
RESET_BOOL3(sp); // Reverse turn
// direction.
}
}
else
{
// Store current angle in TAG5
SP_TAG5(sp) = NORM_ANGLE((SP_TAG5(sp) - 4));
// TAG6 = Turn radius
if (klabs(GetDeltaAngle(SP_TAG5(sp), sp->ang)) >= SP_TAG6(sp))
{
SET_BOOL3(sp); // Reverse turn
// direction.
}
}
}
else if (!TEST_BOOL2(sp))
{
SP_TAG5(sp) = sp->ang; // Copy sprite angle to
// tag5
}
// See if there is a horizon value. 0 defaults to
// 100!
if (SP_TAG7(sp) != 0)
{
camhoriz = SP_TAG7(sp);
if (camhoriz > PLAYER_HORIZ_MAX)
camhoriz = PLAYER_HORIZ_MAX;
else if (camhoriz < PLAYER_HORIZ_MIN)
camhoriz = PLAYER_HORIZ_MIN;
}
else
camhoriz = 100; // Default
// If player is dead still then update at MoveSkip4
// rate.
if (pp->posx == pp->oposx && pp->posy == pp->oposy && pp->posz == pp->oposz)
DoCam = TRUE;
// Set up the tile for drawing
TileFiles.MakeCanvas(mirror[cnt].campic, 128, 128);
{
if (dist < MAXCAMDIST)
{
PLAYERp cp = Player + camplayerview;
if (TEST_BOOL11(sp) && numplayers > 1)
{
drawroomstotile(cp->posx, cp->posy, cp->posz, cp->pang, cp->horiz, cp->cursectnum, mirror[cnt].campic);
}
else
{
drawroomstotile(sp->x, sp->y, sp->z, SP_TAG5(sp), camhoriz, sp->sectnum, mirror[cnt].campic);
}
}
}
}
}
}
}
}
void JS_DrawMirrors(PLAYERp pp, int tx, int ty, int tz, short tpang, int tphoriz)
{
int j, cnt;
int dist;
int tposx, tposy; // Camera
int *longptr;
fix16_t tang;
// int tx, ty, tz, tpang; // Interpolate so mirror doesn't
// drift!
SWBOOL bIsWallMirror = FALSE;
// WARNING! Assuming (MIRRORLABEL&31) = 0 and MAXMIRRORS = 64 <-- JBF: wrong
longptr = (int *)&gotpic[MIRRORLABEL >> 3];
if (longptr && (longptr[0] || longptr[1]))
@ -678,90 +856,6 @@ JS_DrawMirrors(PLAYERp pp, int tx, int ty, int tz, short tpang, int tphoriz)
analyzesprites(dx, dy, dz, FALSE);
renderDrawMasks();
}
else
{
SWBOOL DoCam = FALSE;
if (mirror[cnt].campic == -1)
{
Printf("Missing campic for mirror %d. Map Coordinates: x = %d, y = %d\n", cnt,midx,midy);
return;
}
// BOOL2 = Oscilate camera
if (TEST_BOOL2(sp) && MoveSkip2 == 0)
{
if (TEST_BOOL3(sp)) // If true add increment to
// angle else subtract
{
// Store current angle in TAG5
SP_TAG5(sp) = NORM_ANGLE((SP_TAG5(sp) + 4));
// TAG6 = Turn radius
if (klabs(GetDeltaAngle(SP_TAG5(sp), sp->ang)) >= SP_TAG6(sp))
{
RESET_BOOL3(sp); // Reverse turn
// direction.
}
}
else
{
// Store current angle in TAG5
SP_TAG5(sp) = NORM_ANGLE((SP_TAG5(sp) - 4));
// TAG6 = Turn radius
if (klabs(GetDeltaAngle(SP_TAG5(sp), sp->ang)) >= SP_TAG6(sp))
{
SET_BOOL3(sp); // Reverse turn
// direction.
}
}
}
else if (!TEST_BOOL2(sp))
{
SP_TAG5(sp) = sp->ang; // Copy sprite angle to
// tag5
}
// See if there is a horizon value. 0 defaults to
// 100!
if (SP_TAG7(sp) != 0)
{
camhoriz = SP_TAG7(sp);
if (camhoriz > PLAYER_HORIZ_MAX)
camhoriz = PLAYER_HORIZ_MAX;
else if (camhoriz < PLAYER_HORIZ_MIN)
camhoriz = PLAYER_HORIZ_MIN;
}
else
camhoriz = 100; // Default
// If player is dead still then update at MoveSkip4
// rate.
if (pp->posx == pp->oposx && pp->posy == pp->oposy && pp->posz == pp->oposz)
DoCam = TRUE;
// Set up the tile for drawing
TileFiles.tileCreate(mirror[cnt].campic, 128, 128);
if (MirrorMoveSkip16 == 0 || (DoCam && (MoveSkip4 == 0)))
{
if (dist < MAXCAMDIST)
{
PLAYERp cp = Player + camplayerview;
if (TEST_BOOL11(sp) && numplayers > 1)
{
drawroomstotile(cp->posx, cp->posy, cp->posz, cp->pang, cp->horiz, cp->cursectnum, mirror[cnt].campic);
}
else
{
drawroomstotile(sp->x, sp->y, sp->z, SP_TAG5(sp), camhoriz, sp->sectnum, mirror[cnt].campic);
}
}
}
}
}
else
{

View file

@ -71,6 +71,7 @@ extern SWBOOL mirrorinview;
extern short NormalVisibility;
void JAnalyzeSprites(tspriteptr_t tspr);
void JS_DrawCameras(PLAYERp pp, int tx, int ty, int tz, short tpang, int tphoriz);
void JS_DrawMirrors(PLAYERp pp,int tx,int ty,int tz,short tpang,int tphoriz);
void JS_InitMirrors(void);
void JS_InitLockouts(void);