From 621a9338e530d569c88d2ffe424531a695565f08 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 29 Mar 2020 14:01:46 +0200 Subject: [PATCH] - 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. --- source/build/include/build.h | 4 +- source/build/src/engine.cpp | 110 ++----- source/build/src/polymost.cpp | 20 +- .../rendering/gl/renderer/gl_renderer.cpp | 6 +- source/common/textures/buildtiles.cpp | 25 +- source/common/textures/textures.h | 29 ++ source/duke3d/src/game.cpp | 21 +- source/duke3d/src/game.h | 28 -- source/duke3d/src/sector.cpp | 9 +- source/glbackend/gl_texture.cpp | 16 +- source/rr/src/game.cpp | 37 +-- source/rr/src/game.h | 20 -- source/rr/src/global.h | 1 - source/rr/src/sector.cpp | 9 +- source/sw/src/draw.cpp | 6 + source/sw/src/jsector.cpp | 302 ++++++++++++------ source/sw/src/jsector.h | 1 + 17 files changed, 320 insertions(+), 324 deletions(-) diff --git a/source/build/include/build.h b/source/build/include/build.h index ee9359481..866ac306c 100644 --- a/source/build/include/build.h +++ b/source/build/include/build.h @@ -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); diff --git a/source/build/src/engine.cpp b/source/build/src/engine.cpp index deb58783a..8e52c4069 100644 --- a/source/build/src/engine.cpp +++ b/source/build/src/engine.cpp @@ -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 // diff --git a/source/build/src/polymost.cpp b/source/build/src/polymost.cpp index 0d27cbb64..4a17ddca6 100644 --- a/source/build/src/polymost.cpp +++ b/source/build/src/polymost.cpp @@ -537,14 +537,24 @@ static void polymost_drawpoly(vec2f_t const * const dpxy, int32_t const n, int32 vec2f_t const scale = { 1.f / tsiz2.x, 1.f / tsiz2.y }; auto data = screen->mVertexData->AllocVertices(npoints); auto vt = data.first; - for (bssize_t i = 0; i < npoints; ++i, vt++) + for (bssize_t i = 0; i < npoints; ++i, vt++) { float const r = 1.f / dd[i]; - //update texcoords - vt->SetTexCoord( - uu[i] * r * scale.x - usub, - vv[i] * r * scale.y - vsub); + 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( diff --git a/source/common/rendering/gl/renderer/gl_renderer.cpp b/source/common/rendering/gl/renderer/gl_renderer.cpp index 1c6bfa7cc..d53708ed8 100644 --- a/source/common/rendering/gl/renderer/gl_renderer.cpp +++ b/source/common/rendering/gl/renderer/gl_renderer.cpp @@ -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); } //=========================================================================== diff --git a/source/common/textures/buildtiles.cpp b/source/common/textures/buildtiles.cpp index 37af4da9b..a06b65a67 100644 --- a/source/common/textures/buildtiles.cpp +++ b/source/common/textures/buildtiles.cpp @@ -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) { diff --git a/source/common/textures/textures.h b/source/common/textures/textures.h index 5db5d3a76..c07cdbf8b 100644 --- a/source/common/textures/textures.h +++ b/source/common/textures/textures.h @@ -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); diff --git a/source/duke3d/src/game.cpp b/source/duke3d/src/game.cpp index 2dc9abaea..cd21b4cc1 100644 --- a/source/duke3d/src/game.cpp +++ b/source/duke3d/src/game.cpp @@ -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; diff --git a/source/duke3d/src/game.h b/source/duke3d/src/game.h index e0f50d1b3..237240a62 100644 --- a/source/duke3d/src/game.h +++ b/source/duke3d/src/game.h @@ -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 -static inline int G_GetViewscreenSizeShift(T const * spr) -{ -#if VIEWSCREENFACTOR == 0 - UNREFERENCED_PARAMETER(spr); - return VIEWSCREENFACTOR; -#else - static CONSTEXPR int const mask = (1<xrepeat & mask) | (spr->yrepeat & mask); - - for (int i=0; i < VIEWSCREENFACTOR; i++) - if (rem & (1<= 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 diff --git a/source/glbackend/gl_texture.cpp b/source/glbackend/gl_texture.cpp index 4298ed0d1..fea34c334 100644 --- a/source/glbackend/gl_texture.cpp +++ b/source/glbackend/gl_texture.cpp @@ -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); } - tex = rep->faces[0]; + 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 { diff --git a/source/rr/src/game.cpp b/source/rr/src/game.cpp index 0a1a5dfbf..4e5d419d8 100644 --- a/source/rr/src/game.cpp +++ b/source/rr/src/game.cpp @@ -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; diff --git a/source/rr/src/game.h b/source/rr/src/game.h index f8a5b1cea..7d014b5c5 100644 --- a/source/rr/src/game.h +++ b/source/rr/src/game.h @@ -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 -static inline int G_GetViewscreenSizeShift(T const *tspr) -{ -#if VIEWSCREENFACTOR == 0 - UNREFERENCED_PARAMETER(tspr); - return VIEWSCREENFACTOR; -#else - static const int mask = (1<xrepeat & mask) | (tspr->yrepeat & mask); - - for (bssize_t i=0; i < VIEWSCREENFACTOR; i++) - if (rem & (1<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 diff --git a/source/sw/src/draw.cpp b/source/sw/src/draw.cpp index 01a6e5793..d7279e399 100644 --- a/source/sw/src/draw.cpp +++ b/source/sw/src/draw.cpp @@ -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); diff --git a/source/sw/src/jsector.cpp b/source/sw/src/jsector.cpp index 2bdd02c8f..84829de07 100644 --- a/source/sw/src/jsector.cpp +++ b/source/sw/src/jsector.cpp @@ -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,203 @@ 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; + int tposx, tposy; // Camera + int* longptr; + fix16_t tang; + + // int tx, ty, tz, tpang; // Interpolate so mirror doesn't + // drift! + SWBOOL bIsWallMirror = FALSE; + + camloopcnt += (int32_t)(totalclock - ototalclock); + if (camloopcnt > (60 * 5)) // 5 seconds per player view + { + camloopcnt = 0; + camplayerview++; + if (camplayerview >= numplayers) + 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; @@ -540,17 +729,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 - { - camloopcnt = 0; - camplayerview++; - if (camplayerview >= numplayers) - camplayerview = 1; - } - // 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 { diff --git a/source/sw/src/jsector.h b/source/sw/src/jsector.h index 05f53dcba..be5f96ac0 100644 --- a/source/sw/src/jsector.h +++ b/source/sw/src/jsector.h @@ -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);