From 4f0046105dd615eb88b1eab9f97b03acb5104b1f Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Sun, 10 Jan 2016 21:09:16 -0600 Subject: [PATCH 1/5] Change texture atlas display to show allocated rectangles --- src/win32/fb_d3d9.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/win32/fb_d3d9.cpp b/src/win32/fb_d3d9.cpp index 1641df365..474183086 100644 --- a/src/win32/fb_d3d9.cpp +++ b/src/win32/fb_d3d9.cpp @@ -1833,8 +1833,8 @@ void D3DFB::DrawPackedTextures(int packnum) { D3DCOLOR empty_colors[8] = { - 0xFFFF9999, 0xFF99FF99, 0xFF9999FF, 0xFFFFFF99, - 0xFFFF99FF, 0xFF99FFFF, 0xFFFFCC99, 0xFF99CCFF + 0x80FF0000, 0x8000FF00, 0x800000FF, 0x80FFFF00, + 0x80FF00FF, 0x8000FFFF, 0x80FF8000, 0x800080FF }; Atlas *pack; int x = 8, y = 8; @@ -1869,7 +1869,14 @@ void D3DFB::DrawPackedTextures(int packnum) } AddColorOnlyRect(x-1, y-1-LBOffsetI, 258, 258, D3DCOLOR_XRGB(255,255,0)); - AddColorOnlyQuad(x, y-LBOffsetI, 256, 256, D3DCOLOR_ARGB(180,0,0,0)); + int back = 0; + for (PackedTexture *box = pack->UsedList; box != NULL; box = box->Next) + { + AddColorOnlyQuad(x + box->Area.left, y + box->Area.top, + box->Area.right - box->Area.left, box->Area.bottom - box->Area.top, empty_colors[back]); + back = (back + 1) & 7; + } +// AddColorOnlyQuad(x, y-LBOffsetI, 256, 256, D3DCOLOR_ARGB(180,0,0,0)); CheckQuadBatch(); From 670058fa3c1afb9afababec32afad204dbb7216f Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Sun, 10 Jan 2016 21:54:28 -0600 Subject: [PATCH 2/5] Switch to the bottom-left picker for the Skyline Bin Packer --- src/SkylineBinPack.cpp | 69 +++++++++++++++++++++++++++++++++++++++++- src/SkylineBinPack.h | 3 ++ 2 files changed, 71 insertions(+), 1 deletion(-) diff --git a/src/SkylineBinPack.cpp b/src/SkylineBinPack.cpp index 33f862043..4e9de153e 100644 --- a/src/SkylineBinPack.cpp +++ b/src/SkylineBinPack.cpp @@ -119,7 +119,7 @@ Rect SkylineBinPack::Insert(int width, int height) return newNode; } - return InsertMinWaste(width, height); + return InsertBottomLeft(width, height); } bool SkylineBinPack::RectangleFits(int skylineNodeIndex, int width, int height, int &y) const @@ -254,6 +254,73 @@ void SkylineBinPack::MergeSkylines() } } +Rect SkylineBinPack::InsertBottomLeft(int width, int height) +{ + int bestHeight; + int bestWidth; + int bestIndex; + Rect newNode = FindPositionForNewNodeBottomLeft(width, height, bestHeight, bestWidth, bestIndex); + + if (bestIndex != -1) + { + assert(disjointRects.Disjoint(newNode)); + // Perform the actual packing. + AddSkylineLevel(bestIndex, newNode); + + usedSurfaceArea += width * height; +#ifdef _DEBUG + disjointRects.Add(newNode); +#endif + } + else + memset(&newNode, 0, sizeof(Rect)); + + return newNode; +} + +Rect SkylineBinPack::FindPositionForNewNodeBottomLeft(int width, int height, int &bestHeight, int &bestWidth, int &bestIndex) const +{ + bestHeight = INT_MAX; + bestIndex = -1; + // Used to break ties if there are nodes at the same level. Then pick the narrowest one. + bestWidth = INT_MAX; + Rect newNode = { 0, 0, 0, 0 }; + for(unsigned i = 0; i < skyLine.Size(); ++i) + { + int y; + if (RectangleFits(i, width, height, y)) + { + if (y + height < bestHeight || (y + height == bestHeight && skyLine[i].width < bestWidth)) + { + bestHeight = y + height; + bestIndex = i; + bestWidth = skyLine[i].width; + newNode.x = skyLine[i].x; + newNode.y = y; + newNode.width = width; + newNode.height = height; + assert(disjointRects.Disjoint(newNode)); + } + } +/* if (RectangleFits(i, height, width, y)) + { + if (y + width < bestHeight || (y + width == bestHeight && skyLine[i].width < bestWidth)) + { + bestHeight = y + width; + bestIndex = i; + bestWidth = skyLine[i].width; + newNode.x = skyLine[i].x; + newNode.y = y; + newNode.width = height; + newNode.height = width; + assert(disjointRects.Disjoint(newNode)); + } + } +*/ } + + return newNode; +} + Rect SkylineBinPack::InsertMinWaste(int width, int height) { int bestHeight; diff --git a/src/SkylineBinPack.h b/src/SkylineBinPack.h index f93ddd29d..937c88de6 100644 --- a/src/SkylineBinPack.h +++ b/src/SkylineBinPack.h @@ -72,7 +72,10 @@ private: bool useWasteMap; GuillotineBinPack wasteMap; + Rect InsertBottomLeft(int width, int height); Rect InsertMinWaste(int width, int height); + + Rect FindPositionForNewNodeBottomLeft(int width, int height, int &bestHeight, int &bestWidth, int &bestIndex) const; Rect FindPositionForNewNodeMinWaste(int width, int height, int &bestHeight, int &bestWastedArea, int &bestIndex) const; bool RectangleFits(int skylineNodeIndex, int width, int height, int &y) const; From aaac5ac7a122d7d0cae223964b0624ae3af3c02e Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Sun, 10 Jan 2016 22:01:29 -0600 Subject: [PATCH 3/5] Use not so brilliant backgrounds for allocated atlas backgrounds --- src/win32/fb_d3d9.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/win32/fb_d3d9.cpp b/src/win32/fb_d3d9.cpp index 474183086..bfb618b51 100644 --- a/src/win32/fb_d3d9.cpp +++ b/src/win32/fb_d3d9.cpp @@ -1833,8 +1833,8 @@ void D3DFB::DrawPackedTextures(int packnum) { D3DCOLOR empty_colors[8] = { - 0x80FF0000, 0x8000FF00, 0x800000FF, 0x80FFFF00, - 0x80FF00FF, 0x8000FFFF, 0x80FF8000, 0x800080FF + 0x50FF0000, 0x5000FF00, 0x500000FF, 0x50FFFF00, + 0x50FF00FF, 0x5000FFFF, 0x50FF8000, 0x500080FF }; Atlas *pack; int x = 8, y = 8; From 42e9a6a711816bb2fce51166220cb7d8bc19f063 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Sun, 10 Jan 2016 22:14:35 -0600 Subject: [PATCH 4/5] Make atlas size a macro definition and default it to 512x512 (was 256x256) --- src/win32/fb_d3d9.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/win32/fb_d3d9.cpp b/src/win32/fb_d3d9.cpp index bfb618b51..4e3a14c18 100644 --- a/src/win32/fb_d3d9.cpp +++ b/src/win32/fb_d3d9.cpp @@ -85,6 +85,10 @@ // The number of quads we can batch together. #define MAX_QUAD_BATCH (NUM_INDEXES / 6) +// The default size for a texture atlas. +#define DEF_ATLAS_WIDTH 512 +#define DEF_ATLAS_HEIGHT 512 + // TYPES ------------------------------------------------------------------- IMPLEMENT_CLASS(D3DFB) @@ -1872,8 +1876,11 @@ void D3DFB::DrawPackedTextures(int packnum) int back = 0; for (PackedTexture *box = pack->UsedList; box != NULL; box = box->Next) { - AddColorOnlyQuad(x + box->Area.left, y + box->Area.top, - box->Area.right - box->Area.left, box->Area.bottom - box->Area.top, empty_colors[back]); + AddColorOnlyQuad( + x + box->Area.left * 256 / pack->Width, + y + box->Area.top * 256 / pack->Height, + (box->Area.right - box->Area.left) * 256 / pack->Width, + (box->Area.bottom - box->Area.top) * 256 / pack->Height, empty_colors[back]); back = (back + 1) & 7; } // AddColorOnlyQuad(x, y-LBOffsetI, 256, 256, D3DCOLOR_ARGB(180,0,0,0)); @@ -1980,8 +1987,8 @@ D3DFB::PackedTexture *D3DFB::AllocPackedTexture(int w, int h, bool wrapping, D3D Rect box; bool padded; - // check for 254 to account for padding - if (w > 254 || h > 254 || wrapping) + // The - 2 to account for padding + if (w > 256 - 2 || h > 256 - 2 || wrapping) { // Create a new texture atlas. pack = new Atlas(this, w, h, format); pack->OneUse = true; @@ -2006,7 +2013,7 @@ D3DFB::PackedTexture *D3DFB::AllocPackedTexture(int w, int h, bool wrapping, D3D } if (pack == NULL) { // Create a new texture atlas. - pack = new Atlas(this, 256, 256, format); + pack = new Atlas(this, DEF_ATLAS_WIDTH, DEF_ATLAS_HEIGHT, format); box = pack->Packer.Insert(w, h); } padded = true; From 7115590c1d85e54f5edda4eca04466ad23e6b861 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 11 Jan 2016 15:29:44 +0100 Subject: [PATCH 5/5] - moved setup code for Eternity-style skyboxes to p_spec.cpp and consolidated most of it with nearly identical parts of the stacked sector portal setup code. --- src/g_shared/a_sharedglobal.h | 14 +++++ src/g_shared/a_skies.cpp | 87 --------------------------- src/p_spec.cpp | 108 +++++++++++++++++++++++----------- 3 files changed, 89 insertions(+), 120 deletions(-) diff --git a/src/g_shared/a_sharedglobal.h b/src/g_shared/a_sharedglobal.h index 2688249ea..8a1c31307 100644 --- a/src/g_shared/a_sharedglobal.h +++ b/src/g_shared/a_sharedglobal.h @@ -100,6 +100,20 @@ public: TObjPtr Mate; }; +// For an EE compatible linedef based definition. +class ASkyCamCompat : public ASkyViewpoint +{ + DECLARE_CLASS (ASkyCamCompat, ASkyViewpoint) + +public: + void BeginPlay () + { + // Do not call the SkyViewpoint's super method because it would trash our setup + AActor::BeginPlay(); + } +}; + + class AStackPoint : public ASkyViewpoint { DECLARE_CLASS (AStackPoint, ASkyViewpoint) diff --git a/src/g_shared/a_skies.cpp b/src/g_shared/a_skies.cpp index 1915a260a..ef5623746 100644 --- a/src/g_shared/a_skies.cpp +++ b/src/g_shared/a_skies.cpp @@ -83,95 +83,8 @@ void ASkyViewpoint::Destroy () Super::Destroy(); } -// For an RR compatible linedef based definition. This searches the viewpoint's sector -// for a skybox line special, gets its tag and transfers the skybox to all tagged sectors. -class ASkyCamCompat : public ASkyViewpoint -{ - DECLARE_CLASS (ASkyCamCompat, ASkyViewpoint) - - // skyboxify all tagged sectors - // This involves changing their texture to the sky flat, because while - // EE works with any texture for its skybox portals, ZDoom doesn't. - void SkyboxifySector(sector_t *sector, int plane) - { - // plane: 0=floor, 1=ceiling, 2=both - if (plane == 1 || plane == 2) - { - sector->CeilingSkyBox = this; - sector->SetTexture(sector_t::ceiling, skyflatnum, false); - } - if (plane == 0 || plane == 2) - { - sector->FloorSkyBox = this; - sector->SetTexture(sector_t::floor, skyflatnum, false); - } - } -public: - void BeginPlay (); -}; - IMPLEMENT_CLASS (ASkyCamCompat) -extern FTextureID skyflatnum; - -void ASkyCamCompat::BeginPlay () -{ - if (Sector == NULL) - { - Printf("Sector not initialized for SkyCamCompat\n"); - Sector = P_PointInSector(x, y); - } - if (Sector) - { - line_t * refline = NULL; - for (short i = 0; i < Sector->linecount; i++) - { - refline = Sector->lines[i]; - if (refline->special == Sector_SetPortal && refline->args[1] == 2) - { - // We found the setup linedef for this skybox, so let's use it for our init. - int skybox_id = refline->args[0]; - - // Then, change the alpha - alpha = refline->args[4]; - - FSectorTagIterator it(skybox_id); - int secnum; - while ((secnum = it.Next()) >= 0) - { - SkyboxifySector(§ors[secnum], refline->args[2]); - } - // and finally, check for portal copy linedefs - for (int j=0;jargs[2] || lines[j].args[2] == 3) && - lines[j].args[3] == skybox_id) - { - if (lines[j].args[0] == 0) - { - SkyboxifySector(lines[j].frontsector, refline->args[2]); - } - else - { - FSectorTagIterator itr(lines[j].args[0]); - int s; - while ((s = itr.Next()) >= 0) - { - SkyboxifySector(§ors[s], refline->args[2]); - } - } - } - } - } - } - } - // Do not call the SkyViewpoint's super method because it would trash our setup - AActor::BeginPlay(); -} //--------------------------------------------------------------------------- diff --git a/src/p_spec.cpp b/src/p_spec.cpp index 698cf4f72..08a43fe2a 100644 --- a/src/p_spec.cpp +++ b/src/p_spec.cpp @@ -62,6 +62,7 @@ #include "farchive.h" #include "a_keys.h" #include "c_dispatch.h" +#include "r_sky.h" // State. #include "r_state.h" @@ -71,7 +72,6 @@ #include "r_data/r_interpolate.h" static FRandom pr_playerinspecialsector ("PlayerInSpecialSector"); -void P_SetupPortals(); EXTERN_CVAR(Bool, cl_predict_specials) @@ -986,7 +986,7 @@ void P_SetupPortals() } } -inline void SetPortal(sector_t *sector, int plane, AStackPoint *portal, fixed_t alpha) +static void SetPortal(sector_t *sector, int plane, ASkyViewpoint *portal, fixed_t alpha) { // plane: 0=floor, 1=ceiling, 2=both if (plane > 0) @@ -996,6 +996,8 @@ inline void SetPortal(sector_t *sector, int plane, AStackPoint *portal, fixed_t sector->CeilingSkyBox = portal; if (sector->GetAlpha(sector_t::ceiling) == OPAQUE) sector->SetAlpha(sector_t::ceiling, alpha); + + if (!portal->bAlways) sector->SetTexture(sector_t::ceiling, skyflatnum); } } if (plane == 2 || plane == 0) @@ -1006,6 +1008,42 @@ inline void SetPortal(sector_t *sector, int plane, AStackPoint *portal, fixed_t } if (sector->GetAlpha(sector_t::floor) == OPAQUE) sector->SetAlpha(sector_t::floor, alpha); + + if (!portal->bAlways) sector->SetTexture(sector_t::floor, skyflatnum); + } +} + +static void CopyPortal(int sectortag, int plane, ASkyViewpoint *origin, fixed_t alpha, bool tolines) +{ + int s; + FSectorTagIterator itr(sectortag); + while ((s = itr.Next()) >= 0) + { + SetPortal(§ors[s], plane, origin, alpha); + } + + for (int j=0;j= 0) + { + SetPortal(§ors[s], plane, origin, alpha); + } + } + } } } @@ -1039,42 +1077,39 @@ void P_SpawnPortal(line_t *line, int sectortag, int plane, int alpha) reference->flags |= MF_JUSTATTACKED; anchor->flags |= MF_JUSTATTACKED; - int s; - FSectorTagIterator itr(sectortag); - while ((s = itr.Next()) >= 0) - { - SetPortal(§ors[s], plane, reference, alpha); - } - - for (int j=0;j= 0) - { - SetPortal(§ors[s], plane, reference, alpha); - } - } - } - } - + CopyPortal(sectortag, plane, reference, alpha, false); return; } } } +// This searches the viewpoint's sector +// for a skybox line special, gets its tag and transfers the skybox to all tagged sectors. +void P_SpawnSkybox(ASkyViewpoint *origin) +{ + sector_t *Sector = origin->Sector; + if (Sector == NULL) + { + Printf("Sector not initialized for SkyCamCompat\n"); + origin->Sector = Sector = P_PointInSector(origin->x, origin->y); + } + if (Sector) + { + line_t * refline = NULL; + for (short i = 0; i < Sector->linecount; i++) + { + refline = Sector->lines[i]; + if (refline->special == Sector_SetPortal && refline->args[1] == 2) + { + // We found the setup linedef for this skybox, so let's use it for our init. + CopyPortal(refline->args[0], refline->args[2], origin, 0, true); + return; + } + } + } +} + + // // P_SetSectorDamage @@ -1327,6 +1362,13 @@ void P_SpawnSpecials (void) P_SpawnFriction(); // phares 3/12/98: New friction model using linedefs P_SpawnPushers(); // phares 3/20/98: New pusher model using linedefs + TThinkerIterator it2; + ASkyCamCompat *pt2; + while ((pt2 = it2.Next())) + { + P_SpawnSkybox(pt2); + } + for (i = 0; i < numlines; i++) { switch (lines[i].special)