mirror of
https://github.com/ZDoom/qzdoom-gpl.git
synced 2025-02-21 19:00:56 +00:00
Merge branch 'master' of https://github.com/rheit/zdoom
Conflicts: src/p_spec.cpp
This commit is contained in:
commit
f83b21ff26
6 changed files with 169 additions and 121 deletions
|
@ -119,7 +119,7 @@ Rect SkylineBinPack::Insert(int width, int height)
|
||||||
return newNode;
|
return newNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
return InsertMinWaste(width, height);
|
return InsertBottomLeft(width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SkylineBinPack::RectangleFits(int skylineNodeIndex, int width, int height, int &y) const
|
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)
|
Rect SkylineBinPack::InsertMinWaste(int width, int height)
|
||||||
{
|
{
|
||||||
int bestHeight;
|
int bestHeight;
|
||||||
|
|
|
@ -72,7 +72,10 @@ private:
|
||||||
bool useWasteMap;
|
bool useWasteMap;
|
||||||
GuillotineBinPack wasteMap;
|
GuillotineBinPack wasteMap;
|
||||||
|
|
||||||
|
Rect InsertBottomLeft(int width, int height);
|
||||||
Rect InsertMinWaste(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;
|
Rect FindPositionForNewNodeMinWaste(int width, int height, int &bestHeight, int &bestWastedArea, int &bestIndex) const;
|
||||||
|
|
||||||
bool RectangleFits(int skylineNodeIndex, int width, int height, int &y) const;
|
bool RectangleFits(int skylineNodeIndex, int width, int height, int &y) const;
|
||||||
|
|
|
@ -100,6 +100,20 @@ public:
|
||||||
TObjPtr<ASkyViewpoint> Mate;
|
TObjPtr<ASkyViewpoint> 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
|
class AStackPoint : public ASkyViewpoint
|
||||||
{
|
{
|
||||||
DECLARE_CLASS (AStackPoint, ASkyViewpoint)
|
DECLARE_CLASS (AStackPoint, ASkyViewpoint)
|
||||||
|
|
|
@ -83,95 +83,8 @@ void ASkyViewpoint::Destroy ()
|
||||||
Super::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)
|
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;j<numlines;j++)
|
|
||||||
{
|
|
||||||
// Check if this portal needs to be copied to other sectors
|
|
||||||
// This must be done here to ensure that it gets done only after the portal is set up
|
|
||||||
if (lines[j].special == Sector_SetPortal &&
|
|
||||||
lines[j].args[1] == 1 &&
|
|
||||||
(lines[j].args[2] == refline->args[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();
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -62,6 +62,7 @@
|
||||||
#include "farchive.h"
|
#include "farchive.h"
|
||||||
#include "a_keys.h"
|
#include "a_keys.h"
|
||||||
#include "c_dispatch.h"
|
#include "c_dispatch.h"
|
||||||
|
#include "r_sky.h"
|
||||||
|
|
||||||
// State.
|
// State.
|
||||||
#include "r_state.h"
|
#include "r_state.h"
|
||||||
|
@ -72,7 +73,6 @@
|
||||||
#include "r_data/r_interpolate.h"
|
#include "r_data/r_interpolate.h"
|
||||||
|
|
||||||
static FRandom pr_playerinspecialsector ("PlayerInSpecialSector");
|
static FRandom pr_playerinspecialsector ("PlayerInSpecialSector");
|
||||||
void P_SetupPortals();
|
|
||||||
|
|
||||||
EXTERN_CVAR(Bool, cl_predict_specials)
|
EXTERN_CVAR(Bool, cl_predict_specials)
|
||||||
|
|
||||||
|
@ -987,7 +987,7 @@ void P_SetupPortals()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void SetPortal(sector_t *sector, int plane, ASkyViewpoint *portal, fixed_t alpha)
|
static void SetPortal(sector_t *sector, int plane, ASkyViewpoint *portal, fixed_t alpha)
|
||||||
{
|
{
|
||||||
// plane: 0=floor, 1=ceiling, 2=both
|
// plane: 0=floor, 1=ceiling, 2=both
|
||||||
if (plane > 0)
|
if (plane > 0)
|
||||||
|
@ -1014,6 +1014,40 @@ inline void SetPortal(sector_t *sector, int plane, ASkyViewpoint *portal, fixed_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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<numlines;j++)
|
||||||
|
{
|
||||||
|
// Check if this portal needs to be copied to other sectors
|
||||||
|
// This must be done here to ensure that it gets done only after the portal is set up
|
||||||
|
if (lines[j].special == Sector_SetPortal &&
|
||||||
|
lines[j].args[1] == 1 &&
|
||||||
|
(lines[j].args[2] == plane || lines[j].args[2] == 3) &&
|
||||||
|
lines[j].args[3] == sectortag)
|
||||||
|
{
|
||||||
|
if (lines[j].args[0] == 0)
|
||||||
|
{
|
||||||
|
SetPortal(lines[j].frontsector, plane, origin, alpha);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FSectorTagIterator itr(lines[j].args[0]);
|
||||||
|
while ((s = itr.Next()) >= 0)
|
||||||
|
{
|
||||||
|
SetPortal(§ors[s], plane, origin, alpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void P_SpawnPortal(line_t *line, int sectortag, int plane, int alpha)
|
void P_SpawnPortal(line_t *line, int sectortag, int plane, int alpha)
|
||||||
{
|
{
|
||||||
for (int i=0;i<numlines;i++)
|
for (int i=0;i<numlines;i++)
|
||||||
|
@ -1044,40 +1078,36 @@ void P_SpawnPortal(line_t *line, int sectortag, int plane, int alpha)
|
||||||
reference->flags |= MF_JUSTATTACKED;
|
reference->flags |= MF_JUSTATTACKED;
|
||||||
anchor->flags |= MF_JUSTATTACKED;
|
anchor->flags |= MF_JUSTATTACKED;
|
||||||
|
|
||||||
int s;
|
CopyPortal(sectortag, plane, reference, alpha, false);
|
||||||
FSectorTagIterator itr(sectortag);
|
return;
|
||||||
while ((s = itr.Next()) >= 0)
|
|
||||||
{
|
|
||||||
SetPortal(§ors[s], plane, reference, alpha);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (int j=0;j<numlines;j++)
|
// 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)
|
||||||
{
|
{
|
||||||
// Check if this portal needs to be copied to other sectors
|
Printf("Sector not initialized for SkyCamCompat\n");
|
||||||
// This must be done here to ensure that it gets done only after the portal is set up
|
origin->Sector = Sector = P_PointInSector(origin->x, origin->y);
|
||||||
if (lines[j].special == Sector_SetPortal &&
|
}
|
||||||
lines[j].args[1] == 1 &&
|
if (Sector)
|
||||||
(lines[j].args[2] == plane || lines[j].args[2] == 3) &&
|
|
||||||
lines[j].args[3] == sectortag)
|
|
||||||
{
|
{
|
||||||
if (lines[j].args[0] == 0)
|
line_t * refline = NULL;
|
||||||
|
for (short i = 0; i < Sector->linecount; i++)
|
||||||
{
|
{
|
||||||
SetPortal(lines[j].frontsector, plane, reference, alpha);
|
refline = Sector->lines[i];
|
||||||
}
|
if (refline->special == Sector_SetPortal && refline->args[1] == 2)
|
||||||
else
|
|
||||||
{
|
{
|
||||||
FSectorTagIterator itr(lines[j].args[0]);
|
// We found the setup linedef for this skybox, so let's use it for our init.
|
||||||
while ((s = itr.Next()) >= 0)
|
CopyPortal(refline->args[0], refline->args[2], origin, 0, true);
|
||||||
{
|
return;
|
||||||
SetPortal(§ors[s], plane, reference, alpha);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1373,6 +1403,13 @@ void P_SpawnSpecials (void)
|
||||||
P_SpawnFriction(); // phares 3/12/98: New friction model using linedefs
|
P_SpawnFriction(); // phares 3/12/98: New friction model using linedefs
|
||||||
P_SpawnPushers(); // phares 3/20/98: New pusher model using linedefs
|
P_SpawnPushers(); // phares 3/20/98: New pusher model using linedefs
|
||||||
|
|
||||||
|
TThinkerIterator<ASkyCamCompat> it2;
|
||||||
|
ASkyCamCompat *pt2;
|
||||||
|
while ((pt2 = it2.Next()))
|
||||||
|
{
|
||||||
|
P_SpawnSkybox(pt2);
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < numlines; i++)
|
for (i = 0; i < numlines; i++)
|
||||||
{
|
{
|
||||||
switch (lines[i].special)
|
switch (lines[i].special)
|
||||||
|
|
|
@ -85,6 +85,10 @@
|
||||||
// The number of quads we can batch together.
|
// The number of quads we can batch together.
|
||||||
#define MAX_QUAD_BATCH (NUM_INDEXES / 6)
|
#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 -------------------------------------------------------------------
|
// TYPES -------------------------------------------------------------------
|
||||||
|
|
||||||
IMPLEMENT_CLASS(D3DFB)
|
IMPLEMENT_CLASS(D3DFB)
|
||||||
|
@ -1833,8 +1837,8 @@ void D3DFB::DrawPackedTextures(int packnum)
|
||||||
{
|
{
|
||||||
D3DCOLOR empty_colors[8] =
|
D3DCOLOR empty_colors[8] =
|
||||||
{
|
{
|
||||||
0xFFFF9999, 0xFF99FF99, 0xFF9999FF, 0xFFFFFF99,
|
0x50FF0000, 0x5000FF00, 0x500000FF, 0x50FFFF00,
|
||||||
0xFFFF99FF, 0xFF99FFFF, 0xFFFFCC99, 0xFF99CCFF
|
0x50FF00FF, 0x5000FFFF, 0x50FF8000, 0x500080FF
|
||||||
};
|
};
|
||||||
Atlas *pack;
|
Atlas *pack;
|
||||||
int x = 8, y = 8;
|
int x = 8, y = 8;
|
||||||
|
@ -1869,7 +1873,17 @@ void D3DFB::DrawPackedTextures(int packnum)
|
||||||
}
|
}
|
||||||
|
|
||||||
AddColorOnlyRect(x-1, y-1-LBOffsetI, 258, 258, D3DCOLOR_XRGB(255,255,0));
|
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 * 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));
|
||||||
|
|
||||||
CheckQuadBatch();
|
CheckQuadBatch();
|
||||||
|
|
||||||
|
@ -1973,8 +1987,8 @@ D3DFB::PackedTexture *D3DFB::AllocPackedTexture(int w, int h, bool wrapping, D3D
|
||||||
Rect box;
|
Rect box;
|
||||||
bool padded;
|
bool padded;
|
||||||
|
|
||||||
// check for 254 to account for padding
|
// The - 2 to account for padding
|
||||||
if (w > 254 || h > 254 || wrapping)
|
if (w > 256 - 2 || h > 256 - 2 || wrapping)
|
||||||
{ // Create a new texture atlas.
|
{ // Create a new texture atlas.
|
||||||
pack = new Atlas(this, w, h, format);
|
pack = new Atlas(this, w, h, format);
|
||||||
pack->OneUse = true;
|
pack->OneUse = true;
|
||||||
|
@ -1999,7 +2013,7 @@ D3DFB::PackedTexture *D3DFB::AllocPackedTexture(int w, int h, bool wrapping, D3D
|
||||||
}
|
}
|
||||||
if (pack == NULL)
|
if (pack == NULL)
|
||||||
{ // Create a new texture atlas.
|
{ // 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);
|
box = pack->Packer.Insert(w, h);
|
||||||
}
|
}
|
||||||
padded = true;
|
padded = true;
|
||||||
|
|
Loading…
Reference in a new issue