mirror of
https://github.com/ZDoom/qzdoom-gpl.git
synced 2024-11-16 01:02:03 +00:00
Merged mirrors with portals; Render part of mirrors done, render part of portals needs further testing
This commit is contained in:
parent
662345adb8
commit
cd39c4b8a6
15 changed files with 352 additions and 127 deletions
|
@ -140,7 +140,7 @@ DEFINE_SPECIAL(Teleport_NoStop, 154, 2, 3, 3)
|
|||
// Although ZDoom doesn't support them it's better to have them defined so that
|
||||
// WADs using them somewhere can at least be started without aborting due
|
||||
// to an error message.
|
||||
DEFINE_SPECIAL(SetGlobalFogParameter, 157, 2, 2, 2)
|
||||
DEFINE_SPECIAL(SetGlobalFogParameter, 157, 2, 2, 2) // vavoom? interferes with Line_SetVisualPortal
|
||||
DEFINE_SPECIAL(FS_Execute, 158, 1, 4, 4)
|
||||
DEFINE_SPECIAL(Sector_SetPlaneReflection, 159, 3, 3, 3)
|
||||
DEFINE_SPECIAL(Sector_Set3DFloor, 160, -1, -1, 5)
|
||||
|
@ -236,4 +236,7 @@ DEFINE_SPECIAL(Ceiling_LowerToLowest, 253, 2, 2, 2)
|
|||
DEFINE_SPECIAL(Ceiling_LowerToFloor, 254, 2, 2, 2)
|
||||
DEFINE_SPECIAL(Ceiling_CrushRaiseAndStaySilA, 255, 4, 5, 5)
|
||||
|
||||
DEFINE_SPECIAL(Line_SetVisualPortal, 155, -1, -1, 3)
|
||||
DEFINE_SPECIAL(Line_SetPortal, 156, -1, -1, 3)
|
||||
|
||||
#undef DEFINE_SPECIAL
|
||||
|
|
|
@ -75,6 +75,7 @@
|
|||
#include "actorptrselect.h"
|
||||
#include "farchive.h"
|
||||
#include "decallib.h"
|
||||
#include "portal.h"
|
||||
|
||||
#include "g_shared/a_pickups.h"
|
||||
|
||||
|
@ -8068,6 +8069,9 @@ scriptwait:
|
|||
line->args[4] = STACK(1);
|
||||
DPrintf("Set special on line %d (id %d) to %d(%d,%d,%d,%d,%d)\n",
|
||||
linenum, STACK(7), specnum, arg0, STACK(4), STACK(3), STACK(2), STACK(1));
|
||||
|
||||
// [ZZ] re-link with portals (in case this was something related to portal specials)
|
||||
P_CheckPortal(line);
|
||||
}
|
||||
sp -= 7;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "g_level.h"
|
||||
#include "r_data/colormaps.h"
|
||||
#include "gi.h"
|
||||
#include "portal.h"
|
||||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
||||
|
@ -628,6 +629,11 @@ static void LoadWalls (walltype *walls, int numwalls, sectortype *bsec)
|
|||
}
|
||||
}
|
||||
|
||||
// [ZZ] set initial line portal link
|
||||
// (even though this is rather hard to happen... build doesn't have portals in our sense and it's walls don't get translated into anything like this)
|
||||
for (int i = 0; i < numlines; i++)
|
||||
P_CheckPortal(&lines[i]);
|
||||
|
||||
// Finish setting sector properties that depend on walls
|
||||
for (i = 0; i < numsectors; ++i, ++bsec)
|
||||
{
|
||||
|
|
|
@ -68,6 +68,7 @@
|
|||
#include "po_man.h"
|
||||
#include "r_renderer.h"
|
||||
#include "r_data/colormaps.h"
|
||||
#include "portal.h"
|
||||
|
||||
#include "fragglescript/t_fs.h"
|
||||
|
||||
|
@ -2169,6 +2170,11 @@ void P_LoadLineDefs (MapData * map)
|
|||
if (level.flags2 & LEVEL2_WRAPMIDTEX) ld->flags |= ML_WRAP_MIDTEX;
|
||||
if (level.flags2 & LEVEL2_CHECKSWITCHRANGE) ld->flags |= ML_CHECKSWITCHRANGE;
|
||||
}
|
||||
|
||||
// [ZZ] check initial portal link
|
||||
for (int i = 0; i < numlines; i++)
|
||||
P_CheckPortal(&lines[i]);
|
||||
|
||||
delete[] mldf;
|
||||
}
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include "r_data/colormaps.h"
|
||||
#include "w_wad.h"
|
||||
#include "p_tags.h"
|
||||
#include "portal.h"
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
|
@ -1741,6 +1742,11 @@ public:
|
|||
P_AdjustLine(&lines[line]);
|
||||
P_FinishLoadingLineDef(&lines[line], tempalpha[0]);
|
||||
}
|
||||
|
||||
// [ZZ] check initial portal link
|
||||
for (int i = 0; i < numlines; i++)
|
||||
P_CheckPortal(&lines[i]);
|
||||
|
||||
assert(side <= numsides);
|
||||
if (side < numsides)
|
||||
{
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
#include "r_sky.h"
|
||||
#include "po_man.h"
|
||||
#include "r_data/colormaps.h"
|
||||
#include "portal.h"
|
||||
|
||||
seg_t* curline;
|
||||
side_t* sidedef;
|
||||
|
@ -98,8 +99,8 @@ static BYTE FakeSide;
|
|||
|
||||
int WindowLeft, WindowRight;
|
||||
WORD MirrorFlags;
|
||||
seg_t *ActiveWallMirror;
|
||||
TArray<size_t> WallMirrors;
|
||||
TArray<PortalDrawseg> WallPortals;
|
||||
|
||||
|
||||
static subsector_t *InSubsector;
|
||||
|
||||
|
@ -553,6 +554,10 @@ void R_AddLine (seg_t *line)
|
|||
return;
|
||||
}
|
||||
|
||||
// reject lines that aren't seen from the portal (if any)
|
||||
if (CurrentPortal && P_ClipLineToPortal(line->linedef, CurrentPortal->dst, viewx, viewy))
|
||||
return;
|
||||
|
||||
vertex_t *v1, *v2;
|
||||
|
||||
v1 = line->linedef->v1;
|
||||
|
@ -583,6 +588,8 @@ void R_AddLine (seg_t *line)
|
|||
rw_mustmarkfloor = rw_mustmarkceiling = false;
|
||||
rw_havehigh = rw_havelow = false;
|
||||
|
||||
bool is_portal = (line->linedef && line->linedef->special == Line_Mirror);
|
||||
|
||||
// Single sided line?
|
||||
if (backsector == NULL)
|
||||
{
|
||||
|
@ -649,7 +656,9 @@ void R_AddLine (seg_t *line)
|
|||
// Window.
|
||||
solid = false;
|
||||
}
|
||||
else if (backsector->lightlevel != frontsector->lightlevel
|
||||
else if (is_portal
|
||||
|
||||
|| backsector->lightlevel != frontsector->lightlevel
|
||||
|| backsector->GetTexture(sector_t::floor) != frontsector->GetTexture(sector_t::floor)
|
||||
|| backsector->GetTexture(sector_t::ceiling) != frontsector->GetTexture(sector_t::ceiling)
|
||||
|| curline->sidedef->GetTexture(side_t::mid).isValid()
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
#include "tarray.h"
|
||||
#include <stddef.h>
|
||||
#include "portal.h"
|
||||
|
||||
// The 3072 below is just an arbitrary value picked to avoid
|
||||
// drawing lines the player is too close to that would overflow
|
||||
|
@ -86,6 +87,7 @@ struct drawseg_t
|
|||
// backups
|
||||
ptrdiff_t bkup; // sprtopclip backup, for mid and fake textures
|
||||
FWallTmapVals tmapvals;
|
||||
int CurrentPortalUniq; // [ZZ] to identify the portal that this drawseg is in. used for sprite clipping.
|
||||
};
|
||||
|
||||
|
||||
|
@ -104,9 +106,8 @@ extern size_t FirstInterestingDrawseg;
|
|||
|
||||
extern int WindowLeft, WindowRight;
|
||||
extern WORD MirrorFlags;
|
||||
extern seg_t* ActiveWallMirror;
|
||||
|
||||
extern TArray<size_t> WallMirrors;
|
||||
extern TArray<PortalDrawseg> WallPortals;
|
||||
|
||||
typedef void (*drawfunc_t) (int start, int stop);
|
||||
|
||||
|
|
|
@ -894,6 +894,10 @@ struct line_t
|
|||
sector_t *frontsector, *backsector;
|
||||
int validcount; // if == validcount, already checked
|
||||
int locknumber; // [Dusk] lock number for special
|
||||
bool portal;
|
||||
bool portal_mirror;
|
||||
bool portal_passive;
|
||||
line_t *portal_dst;
|
||||
};
|
||||
|
||||
// phares 3/14/98
|
||||
|
|
163
src/r_main.cpp
163
src/r_main.cpp
|
@ -57,6 +57,7 @@
|
|||
#include "v_font.h"
|
||||
#include "r_data/colormaps.h"
|
||||
#include "farchive.h"
|
||||
#include "portal.h"
|
||||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
||||
|
@ -608,52 +609,91 @@ void R_SetupFreelook()
|
|||
|
||||
//==========================================================================
|
||||
//
|
||||
// R_EnterMirror
|
||||
// R_EnterPortal
|
||||
//
|
||||
// [RH] Draw the reflection inside a mirror
|
||||
// [ZZ] Merged with portal code, originally called R_EnterMirror
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void R_EnterMirror (drawseg_t *ds, int depth)
|
||||
void R_EnterPortal (PortalDrawseg* pds, int depth)
|
||||
{
|
||||
// [ZZ] check depth. fill portal with black if it's exceeding the visual recursion limit, and continue like nothing happened.
|
||||
if (depth > 4)
|
||||
{
|
||||
BYTE color = (BYTE)BestColor((DWORD *)GPalette.BaseColors, 0, 0, 0, 0, 255);
|
||||
int spacing = RenderTarget->GetPitch();
|
||||
for (int x = pds->x1; x <= pds->x2; x++)
|
||||
{
|
||||
int Ytop = pds->ceilingclip[x-pds->x1];
|
||||
int Ybottom = pds->floorclip[x-pds->x1];
|
||||
|
||||
BYTE *dest = RenderTarget->GetBuffer() + x + Ytop * spacing;
|
||||
|
||||
if (Ytop < 0) Ytop = 0;
|
||||
if (Ybottom >= RenderTarget->GetHeight())
|
||||
Ybottom = RenderTarget->GetHeight()-1;
|
||||
|
||||
for (int y = Ytop; y <= Ybottom; y++)
|
||||
{
|
||||
*dest = color;
|
||||
dest += spacing;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
angle_t startang = viewangle;
|
||||
fixed_t startx = viewx;
|
||||
fixed_t starty = viewy;
|
||||
|
||||
CurrentMirror++;
|
||||
int prevuniq = CurrentPortalUniq;
|
||||
CurrentPortalUniq++;
|
||||
|
||||
unsigned int mirrorsAtStart = WallMirrors.Size ();
|
||||
unsigned int portalsAtStart = WallPortals.Size ();
|
||||
|
||||
vertex_t *v1 = ds->curline->v1;
|
||||
if (pds->mirror)
|
||||
{
|
||||
//vertex_t *v1 = ds->curline->v1;
|
||||
vertex_t *v1 = pds->src->v1;
|
||||
|
||||
// Reflect the current view behind the mirror.
|
||||
if (pds->src->dx == 0)
|
||||
{ // vertical mirror
|
||||
viewx = v1->x - startx + v1->x;
|
||||
}
|
||||
else if (pds->src->dy == 0)
|
||||
{ // horizontal mirror
|
||||
viewy = v1->y - starty + v1->y;
|
||||
}
|
||||
else
|
||||
{ // any mirror--use floats to avoid integer overflow
|
||||
vertex_t *v2 = pds->src->v2;
|
||||
|
||||
float dx = FIXED2FLOAT(v2->x - v1->x);
|
||||
float dy = FIXED2FLOAT(v2->y - v1->y);
|
||||
float x1 = FIXED2FLOAT(v1->x);
|
||||
float y1 = FIXED2FLOAT(v1->y);
|
||||
float x = FIXED2FLOAT(startx);
|
||||
float y = FIXED2FLOAT(starty);
|
||||
|
||||
// the above two cases catch len == 0
|
||||
float r = ((x - x1)*dx + (y - y1)*dy) / (dx*dx + dy*dy);
|
||||
|
||||
viewx = FLOAT2FIXED((x1 + r * dx)*2 - x);
|
||||
viewy = FLOAT2FIXED((y1 + r * dy)*2 - y);
|
||||
}
|
||||
viewangle = 2*R_PointToAngle2 (pds->src->v1->x, pds->src->v1->y,
|
||||
pds->src->v2->x, pds->src->v2->y) - startang;
|
||||
|
||||
// Reflect the current view behind the mirror.
|
||||
if (ds->curline->linedef->dx == 0)
|
||||
{ // vertical mirror
|
||||
viewx = v1->x - startx + v1->x;
|
||||
}
|
||||
else if (ds->curline->linedef->dy == 0)
|
||||
{ // horizontal mirror
|
||||
viewy = v1->y - starty + v1->y;
|
||||
}
|
||||
else
|
||||
{ // any mirror--use floats to avoid integer overflow
|
||||
vertex_t *v2 = ds->curline->v2;
|
||||
|
||||
float dx = FIXED2FLOAT(v2->x - v1->x);
|
||||
float dy = FIXED2FLOAT(v2->y - v1->y);
|
||||
float x1 = FIXED2FLOAT(v1->x);
|
||||
float y1 = FIXED2FLOAT(v1->y);
|
||||
float x = FIXED2FLOAT(startx);
|
||||
float y = FIXED2FLOAT(starty);
|
||||
|
||||
// the above two cases catch len == 0
|
||||
float r = ((x - x1)*dx + (y - y1)*dy) / (dx*dx + dy*dy);
|
||||
|
||||
viewx = FLOAT2FIXED((x1 + r * dx)*2 - x);
|
||||
viewy = FLOAT2FIXED((y1 + r * dy)*2 - y);
|
||||
{
|
||||
P_TranslatePortalXY(pds->src, pds->dst, viewx, viewy);
|
||||
P_TranslatePortalZ(pds->src, pds->dst, viewz);
|
||||
P_TranslatePortalAngle(pds->src, pds->dst, viewangle);
|
||||
}
|
||||
viewangle = 2*R_PointToAngle2 (ds->curline->v1->x, ds->curline->v1->y,
|
||||
ds->curline->v2->x, ds->curline->v2->y) - startang;
|
||||
|
||||
viewsin = finesine[viewangle>>ANGLETOFINESHIFT];
|
||||
viewcos = finecosine[viewangle>>ANGLETOFINESHIFT];
|
||||
|
@ -664,35 +704,57 @@ void R_EnterMirror (drawseg_t *ds, int depth)
|
|||
R_CopyStackedViewParameters();
|
||||
|
||||
validcount++;
|
||||
ActiveWallMirror = ds->curline;
|
||||
PortalDrawseg* prevpds = CurrentPortal;
|
||||
CurrentPortal = pds;
|
||||
|
||||
R_ClearPlanes (false);
|
||||
R_ClearClipSegs (ds->x1, ds->x2 + 1);
|
||||
R_ClearClipSegs (pds->x1, pds->x2 + 1); // todo: check if this "+1" is actually needed
|
||||
|
||||
memcpy (ceilingclip + ds->x1, openings + ds->sprtopclip, (ds->x2 - ds->x1 + 1)*sizeof(*ceilingclip));
|
||||
memcpy (floorclip + ds->x1, openings + ds->sprbottomclip, (ds->x2 - ds->x1 + 1)*sizeof(*floorclip));
|
||||
// some portals have height differences, account for this here
|
||||
R_3D_EnterSkybox(); // push 3D floor height map
|
||||
|
||||
WindowLeft = ds->x1;
|
||||
WindowRight = ds->x2;
|
||||
MirrorFlags = (depth + 1) & 1;
|
||||
memcpy (ceilingclip + pds->x1, &pds->ceilingclip[0], pds->ceilingclip.Size()*sizeof(*ceilingclip));
|
||||
memcpy (floorclip + pds->x1, &pds->floorclip[0], pds->floorclip.Size()*sizeof(*floorclip));
|
||||
|
||||
WindowLeft = pds->x1;
|
||||
WindowRight = pds->x2;
|
||||
|
||||
// RF_XFLIP should be removed before calling the root function
|
||||
int prevmf = MirrorFlags;
|
||||
if (pds->mirror)
|
||||
{
|
||||
if (MirrorFlags & RF_XFLIP)
|
||||
MirrorFlags &= ~RF_XFLIP;
|
||||
else MirrorFlags |= RF_XFLIP;
|
||||
}
|
||||
|
||||
R_RenderBSPNode (nodes + numnodes - 1);
|
||||
R_3D_ResetClip(); // reset clips (floor/ceiling)
|
||||
|
||||
PlaneCycles.Clock();
|
||||
R_DrawPlanes ();
|
||||
R_DrawSkyBoxes ();
|
||||
PlaneCycles.Unclock();
|
||||
|
||||
// Allow up to 4 recursions through a mirror
|
||||
if (depth < 4)
|
||||
// depth check is in another place right now
|
||||
unsigned int portalsAtEnd = WallPortals.Size ();
|
||||
for (; portalsAtStart < portalsAtEnd; portalsAtStart++)
|
||||
{
|
||||
unsigned int mirrorsAtEnd = WallMirrors.Size ();
|
||||
|
||||
for (; mirrorsAtStart < mirrorsAtEnd; mirrorsAtStart++)
|
||||
{
|
||||
R_EnterMirror (drawsegs + WallMirrors[mirrorsAtStart], depth + 1);
|
||||
}
|
||||
R_EnterPortal (&WallPortals[portalsAtStart], depth + 1);
|
||||
}
|
||||
|
||||
NetUpdate();
|
||||
|
||||
MaskedCycles.Clock(); // [ZZ] count sprites in portals/mirrors along with normal ones.
|
||||
R_DrawMasked (); // this is required since with portals there often will be cases when more than 80% of the view is inside a portal.
|
||||
MaskedCycles.Unclock();
|
||||
|
||||
NetUpdate();
|
||||
|
||||
R_3D_LeaveSkybox(); // pop 3D floor height map
|
||||
CurrentPortal = prevpds;
|
||||
MirrorFlags = prevmf;
|
||||
CurrentPortalUniq = prevuniq;
|
||||
viewangle = startang;
|
||||
viewx = startx;
|
||||
viewy = starty;
|
||||
|
@ -779,7 +841,7 @@ void R_RenderActorView (AActor *actor, bool dontmaplines)
|
|||
WindowLeft = 0;
|
||||
WindowRight = viewwidth - 1;
|
||||
MirrorFlags = 0;
|
||||
ActiveWallMirror = NULL;
|
||||
CurrentPortal = NULL;
|
||||
|
||||
r_dontmaplines = dontmaplines;
|
||||
|
||||
|
@ -813,10 +875,11 @@ void R_RenderActorView (AActor *actor, bool dontmaplines)
|
|||
PlaneCycles.Unclock();
|
||||
|
||||
// [RH] Walk through mirrors
|
||||
size_t lastmirror = WallMirrors.Size ();
|
||||
for (unsigned int i = 0; i < lastmirror; i++)
|
||||
// [ZZ] Merged with portals
|
||||
size_t lastportal = WallPortals.Size();
|
||||
for (unsigned int i = 0; i < lastportal; i++)
|
||||
{
|
||||
R_EnterMirror (drawsegs + WallMirrors[i], 0);
|
||||
R_EnterPortal(&WallPortals[i], 0);
|
||||
}
|
||||
|
||||
NetUpdate ();
|
||||
|
@ -827,7 +890,7 @@ void R_RenderActorView (AActor *actor, bool dontmaplines)
|
|||
|
||||
NetUpdate ();
|
||||
}
|
||||
WallMirrors.Clear ();
|
||||
WallPortals.Clear ();
|
||||
interpolator.RestoreInterpolations ();
|
||||
R_SetupBuffer ();
|
||||
|
||||
|
|
|
@ -58,6 +58,7 @@
|
|||
#include "r_3dfloors.h"
|
||||
#include "v_palette.h"
|
||||
#include "r_data/colormaps.h"
|
||||
#include "portal.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4244)
|
||||
|
@ -686,7 +687,7 @@ visplane_t *R_FindPlane (const secplane_t &height, FTextureID picnum, int lightl
|
|||
yscale == check->yscale &&
|
||||
angle == check->angle &&
|
||||
sky == check->sky &&
|
||||
CurrentMirror == check->CurrentMirror &&
|
||||
CurrentPortalUniq == check->CurrentPortalUniq &&
|
||||
MirrorFlags == check->MirrorFlags &&
|
||||
CurrentSkybox == check->CurrentSkybox
|
||||
)
|
||||
|
@ -718,7 +719,7 @@ visplane_t *R_FindPlane (const secplane_t &height, FTextureID picnum, int lightl
|
|||
check->viewangle = stacked_angle;
|
||||
check->Alpha = alpha;
|
||||
check->Additive = additive;
|
||||
check->CurrentMirror = CurrentMirror;
|
||||
check->CurrentPortalUniq = CurrentPortalUniq;
|
||||
check->MirrorFlags = MirrorFlags;
|
||||
check->CurrentSkybox = CurrentSkybox;
|
||||
|
||||
|
@ -807,7 +808,7 @@ visplane_t *R_CheckPlane (visplane_t *pl, int start, int stop)
|
|||
new_pl->sky = pl->sky;
|
||||
new_pl->Alpha = pl->Alpha;
|
||||
new_pl->Additive = pl->Additive;
|
||||
new_pl->CurrentMirror = pl->CurrentMirror;
|
||||
new_pl->CurrentPortalUniq = pl->CurrentPortalUniq;
|
||||
new_pl->MirrorFlags = pl->MirrorFlags;
|
||||
new_pl->CurrentSkybox = pl->CurrentSkybox;
|
||||
pl = new_pl;
|
||||
|
@ -1043,7 +1044,7 @@ int R_DrawPlanes ()
|
|||
for (pl = visplanes[i]; pl; pl = pl->next)
|
||||
{
|
||||
// kg3D - draw only correct planes
|
||||
if(pl->CurrentMirror != CurrentMirror || pl->CurrentSkybox != CurrentSkybox)
|
||||
if(pl->CurrentPortalUniq != CurrentPortalUniq || pl->CurrentSkybox != CurrentSkybox)
|
||||
continue;
|
||||
// kg3D - draw only real planes now
|
||||
if(pl->sky >= 0) {
|
||||
|
@ -1269,6 +1270,7 @@ void R_DrawSkyBoxes ()
|
|||
|
||||
// Create a drawseg to clip sprites to the sky plane
|
||||
R_CheckDrawSegs ();
|
||||
ds_p->CurrentPortalUniq = CurrentPortalUniq;
|
||||
ds_p->siz1 = INT_MAX;
|
||||
ds_p->siz2 = INT_MAX;
|
||||
ds_p->sz1 = 0;
|
||||
|
|
|
@ -58,7 +58,7 @@ struct visplane_s
|
|||
|
||||
// kg3D - keep track of mirror and skybox owner
|
||||
int CurrentSkybox;
|
||||
int CurrentMirror; // mirror counter, counts all of them
|
||||
int CurrentPortalUniq; // mirror counter, counts all of them
|
||||
int MirrorFlags; // this is not related to CurrentMirror
|
||||
|
||||
unsigned short *bottom; // [RH] bottom and top arrays are dynamically
|
||||
|
|
130
src/r_segs.cpp
130
src/r_segs.cpp
|
@ -52,6 +52,7 @@
|
|||
#include "r_3dfloors.h"
|
||||
#include "v_palette.h"
|
||||
#include "r_data/colormaps.h"
|
||||
#include "portal.h"
|
||||
|
||||
#define WALLYREPEAT 8
|
||||
|
||||
|
@ -103,7 +104,7 @@ extern fixed_t rw_frontfz1, rw_frontfz2;
|
|||
int rw_ceilstat, rw_floorstat;
|
||||
bool rw_mustmarkfloor, rw_mustmarkceiling;
|
||||
bool rw_prepped;
|
||||
bool rw_markmirror;
|
||||
bool rw_markportal;
|
||||
bool rw_havehigh;
|
||||
bool rw_havelow;
|
||||
|
||||
|
@ -1948,7 +1949,7 @@ void R_NewWall (bool needlights)
|
|||
{
|
||||
fixed_t rowoffset, yrepeat;
|
||||
|
||||
rw_markmirror = false;
|
||||
rw_markportal = false;
|
||||
|
||||
sidedef = curline->sidedef;
|
||||
linedef = curline->linedef;
|
||||
|
@ -1958,65 +1959,64 @@ void R_NewWall (bool needlights)
|
|||
|
||||
midtexture = toptexture = bottomtexture = 0;
|
||||
|
||||
if (backsector == NULL)
|
||||
if (sidedef == linedef->sidedef[0] &&
|
||||
linedef->portal &&
|
||||
(!linedef->portal_mirror || r_drawmirrors)) // [ZZ] compatibility with r_drawmirrors cvar that existed way before portals
|
||||
{
|
||||
markfloor = markceiling = true; // act like an one-sided wall here (todo: check how does this work with transparency)
|
||||
rw_markportal = true;
|
||||
}
|
||||
else if (backsector == NULL)
|
||||
{
|
||||
// single sided line
|
||||
// a single sided line is terminal, so it must mark ends
|
||||
markfloor = markceiling = true;
|
||||
// [RH] Render mirrors later, but mark them now.
|
||||
if (linedef->special != Line_Mirror || !r_drawmirrors)
|
||||
// [RH] Horizon lines do not need to be textured
|
||||
if (linedef->special != Line_Horizon)
|
||||
{
|
||||
// [RH] Horizon lines do not need to be textured
|
||||
if (linedef->special != Line_Horizon)
|
||||
{
|
||||
midtexture = TexMan(sidedef->GetTexture(side_t::mid), true);
|
||||
rw_offset_mid = sidedef->GetTextureXOffset(side_t::mid);
|
||||
rowoffset = sidedef->GetTextureYOffset(side_t::mid);
|
||||
rw_midtexturescalex = sidedef->GetTextureXScale(side_t::mid);
|
||||
rw_midtexturescaley = sidedef->GetTextureYScale(side_t::mid);
|
||||
yrepeat = FixedMul(midtexture->yScale, rw_midtexturescaley);
|
||||
if (yrepeat >= 0)
|
||||
{ // normal orientation
|
||||
if (linedef->flags & ML_DONTPEGBOTTOM)
|
||||
{ // bottom of texture at bottom
|
||||
rw_midtexturemid = MulScale16(frontsector->GetPlaneTexZ(sector_t::floor) - viewz, yrepeat) + (midtexture->GetHeight() << FRACBITS);
|
||||
}
|
||||
else
|
||||
{ // top of texture at top
|
||||
rw_midtexturemid = MulScale16(frontsector->GetPlaneTexZ(sector_t::ceiling) - viewz, yrepeat);
|
||||
if (rowoffset < 0 && midtexture != NULL)
|
||||
{
|
||||
rowoffset += midtexture->GetHeight() << FRACBITS;
|
||||
}
|
||||
}
|
||||
midtexture = TexMan(sidedef->GetTexture(side_t::mid), true);
|
||||
rw_offset_mid = sidedef->GetTextureXOffset(side_t::mid);
|
||||
rowoffset = sidedef->GetTextureYOffset(side_t::mid);
|
||||
rw_midtexturescalex = sidedef->GetTextureXScale(side_t::mid);
|
||||
rw_midtexturescaley = sidedef->GetTextureYScale(side_t::mid);
|
||||
yrepeat = FixedMul(midtexture->yScale, rw_midtexturescaley);
|
||||
if (yrepeat >= 0)
|
||||
{ // normal orientation
|
||||
if (linedef->flags & ML_DONTPEGBOTTOM)
|
||||
{ // bottom of texture at bottom
|
||||
rw_midtexturemid = MulScale16(frontsector->GetPlaneTexZ(sector_t::floor) - viewz, yrepeat) + (midtexture->GetHeight() << FRACBITS);
|
||||
}
|
||||
else
|
||||
{ // upside down
|
||||
rowoffset = -rowoffset;
|
||||
if (linedef->flags & ML_DONTPEGBOTTOM)
|
||||
{ // top of texture at bottom
|
||||
rw_midtexturemid = MulScale16(frontsector->GetPlaneTexZ(sector_t::floor) - viewz, yrepeat);
|
||||
{ // top of texture at top
|
||||
rw_midtexturemid = MulScale16(frontsector->GetPlaneTexZ(sector_t::ceiling) - viewz, yrepeat);
|
||||
if (rowoffset < 0 && midtexture != NULL)
|
||||
{
|
||||
rowoffset += midtexture->GetHeight() << FRACBITS;
|
||||
}
|
||||
else
|
||||
{ // bottom of texture at top
|
||||
rw_midtexturemid = MulScale16(frontsector->GetPlaneTexZ(sector_t::ceiling) - viewz, yrepeat) + (midtexture->GetHeight() << FRACBITS);
|
||||
}
|
||||
}
|
||||
if (midtexture->bWorldPanning)
|
||||
{
|
||||
rw_midtexturemid += MulScale16(rowoffset, yrepeat);
|
||||
}
|
||||
else
|
||||
{
|
||||
// rowoffset is added outside the multiply so that it positions the texture
|
||||
// by texels instead of world units.
|
||||
rw_midtexturemid += rowoffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rw_markmirror = true;
|
||||
else
|
||||
{ // upside down
|
||||
rowoffset = -rowoffset;
|
||||
if (linedef->flags & ML_DONTPEGBOTTOM)
|
||||
{ // top of texture at bottom
|
||||
rw_midtexturemid = MulScale16(frontsector->GetPlaneTexZ(sector_t::floor) - viewz, yrepeat);
|
||||
}
|
||||
else
|
||||
{ // bottom of texture at top
|
||||
rw_midtexturemid = MulScale16(frontsector->GetPlaneTexZ(sector_t::ceiling) - viewz, yrepeat) + (midtexture->GetHeight() << FRACBITS);
|
||||
}
|
||||
}
|
||||
if (midtexture->bWorldPanning)
|
||||
{
|
||||
rw_midtexturemid += MulScale16(rowoffset, yrepeat);
|
||||
}
|
||||
else
|
||||
{
|
||||
// rowoffset is added outside the multiply so that it positions the texture
|
||||
// by texels instead of world units.
|
||||
rw_midtexturemid += rowoffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -2339,6 +2339,7 @@ void R_StoreWallRange (int start, int stop)
|
|||
rw_offset = sidedef->GetTextureXOffset(side_t::mid);
|
||||
rw_light = rw_lightleft + rw_lightstep * (start - WallC.sx1);
|
||||
|
||||
ds_p->CurrentPortalUniq = CurrentPortalUniq;
|
||||
ds_p->sx1 = WallC.sx1;
|
||||
ds_p->sx2 = WallC.sx2;
|
||||
ds_p->sz1 = WallC.sz1;
|
||||
|
@ -2362,10 +2363,8 @@ void R_StoreWallRange (int start, int stop)
|
|||
// killough 1/6/98, 2/1/98: remove limit on openings
|
||||
ds_p->sprtopclip = ds_p->sprbottomclip = ds_p->maskedtexturecol = ds_p->bkup = ds_p->swall = -1;
|
||||
|
||||
if (rw_markmirror)
|
||||
if (rw_markportal)
|
||||
{
|
||||
size_t drawsegnum = ds_p - drawsegs;
|
||||
WallMirrors.Push (drawsegnum);
|
||||
ds_p->silhouette = SIL_BOTH;
|
||||
}
|
||||
else if (backsector == NULL)
|
||||
|
@ -2576,9 +2575,28 @@ void R_StoreWallRange (int start, int stop)
|
|||
}
|
||||
|
||||
// [RH] Draw any decals bound to the seg
|
||||
for (DBaseDecal *decal = curline->sidedef->AttachedDecals; decal != NULL; decal = decal->WallNext)
|
||||
// [ZZ] Only if not an active mirror
|
||||
if (!rw_markportal)
|
||||
{
|
||||
R_RenderDecal (curline->sidedef, decal, ds_p, 0);
|
||||
for (DBaseDecal *decal = curline->sidedef->AttachedDecals; decal != NULL; decal = decal->WallNext)
|
||||
{
|
||||
R_RenderDecal (curline->sidedef, decal, ds_p, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (rw_markportal)
|
||||
{
|
||||
PortalDrawseg pds;
|
||||
pds.src = curline->linedef;
|
||||
pds.dst = curline->linedef->portal_dst;
|
||||
pds.x1 = ds_p->x1;
|
||||
pds.x2 = ds_p->x2;
|
||||
pds.ceilingclip.Resize((pds.x2-pds.x1)+1);
|
||||
memcpy(&pds.ceilingclip[0], openings + ds_p->sprtopclip, pds.ceilingclip.Size()*sizeof(*openings));
|
||||
pds.floorclip.Resize((pds.x2-pds.x1)+1);
|
||||
memcpy(&pds.floorclip[0], openings + ds_p->sprbottomclip, pds.floorclip.Size()*sizeof(*openings));
|
||||
pds.mirror = curline->linedef->portal_mirror;
|
||||
WallPortals.Push(pds);
|
||||
}
|
||||
|
||||
ds_p++;
|
||||
|
|
110
src/r_things.cpp
110
src/r_things.cpp
|
@ -317,6 +317,44 @@ nextpost:
|
|||
}
|
||||
}
|
||||
|
||||
// [ZZ]
|
||||
// R_ClipSpriteColumnWithPortals
|
||||
//
|
||||
bool R_ClipSpriteColumnWithPortals (fixed_t x, fixed_t y, vissprite_t* spr)
|
||||
{
|
||||
size_t numdrawsegs = ds_p-firstdrawseg;
|
||||
for (int i = (int)numdrawsegs-1; i >= 0; i--)
|
||||
{
|
||||
drawseg_t* seg = &firstdrawseg[i];
|
||||
|
||||
// ignore segs from other portals
|
||||
if (seg->CurrentPortalUniq != CurrentPortalUniq)
|
||||
continue;
|
||||
|
||||
line_t* line = seg->curline->linedef;
|
||||
// divline? wtf, anyway, divlines aren't supposed to be drawn. But I definitely saw NULL linedefs in drawsegs.
|
||||
if (!line) continue;
|
||||
|
||||
// check if this line will clip sprites to itself
|
||||
if (!line->portal)
|
||||
continue;
|
||||
|
||||
// don't clip sprites with portal's back side (it's transparent)
|
||||
if (seg->curline->sidedef != line->sidedef[0])
|
||||
continue;
|
||||
|
||||
// don't clip if the sprite is in front of the portal
|
||||
if (!P_PointOnLineSide(x, y, line))
|
||||
continue;
|
||||
|
||||
// now if current column is covered by this drawseg, we clip it away
|
||||
if ((dc_x >= seg->x1) && (dc_x <= seg->x2))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// R_DrawVisSprite
|
||||
// mfloorclip and mceilingclip should also be set.
|
||||
|
@ -330,6 +368,7 @@ void R_DrawVisSprite (vissprite_t *vis)
|
|||
int x2, stop4;
|
||||
fixed_t xiscale;
|
||||
ESPSResult mode;
|
||||
bool ispsprite = (!vis->sector && !vis->gx && !vis->gy && !vis->gz);
|
||||
|
||||
dc_colormap = vis->Style.colormap;
|
||||
|
||||
|
@ -373,7 +412,8 @@ void R_DrawVisSprite (vissprite_t *vis)
|
|||
while ((dc_x < stop4) && (dc_x & 3))
|
||||
{
|
||||
pixels = tex->GetColumn (frac >> FRACBITS, &spans);
|
||||
R_DrawMaskedColumn (pixels, spans);
|
||||
if (ispsprite || !R_ClipSpriteColumnWithPortals(vis->gx, vis->gy, vis))
|
||||
R_DrawMaskedColumn (pixels, spans);
|
||||
dc_x++;
|
||||
frac += xiscale;
|
||||
}
|
||||
|
@ -384,7 +424,8 @@ void R_DrawVisSprite (vissprite_t *vis)
|
|||
for (int zz = 4; zz; --zz)
|
||||
{
|
||||
pixels = tex->GetColumn (frac >> FRACBITS, &spans);
|
||||
R_DrawMaskedColumnHoriz (pixels, spans);
|
||||
if (ispsprite || !R_ClipSpriteColumnWithPortals(vis->gx, vis->gy, vis))
|
||||
R_DrawMaskedColumnHoriz (pixels, spans);
|
||||
dc_x++;
|
||||
frac += xiscale;
|
||||
}
|
||||
|
@ -394,7 +435,8 @@ void R_DrawVisSprite (vissprite_t *vis)
|
|||
while (dc_x < x2)
|
||||
{
|
||||
pixels = tex->GetColumn (frac >> FRACBITS, &spans);
|
||||
R_DrawMaskedColumn (pixels, spans);
|
||||
if (ispsprite || !R_ClipSpriteColumnWithPortals(vis->gx, vis->gy, vis))
|
||||
R_DrawMaskedColumn (pixels, spans);
|
||||
dc_x++;
|
||||
frac += xiscale;
|
||||
}
|
||||
|
@ -504,7 +546,8 @@ void R_DrawWallSprite(vissprite_t *spr)
|
|||
{ // calculate lighting
|
||||
dc_colormap = usecolormap->Maps + (GETPALOOKUP (rw_light, shade) << COLORMAPSHIFT);
|
||||
}
|
||||
R_WallSpriteColumn(R_DrawMaskedColumn);
|
||||
if (!R_ClipSpriteColumnWithPortals(spr->gx, spr->gy, spr))
|
||||
R_WallSpriteColumn(R_DrawMaskedColumn);
|
||||
dc_x++;
|
||||
}
|
||||
|
||||
|
@ -517,7 +560,8 @@ void R_DrawWallSprite(vissprite_t *spr)
|
|||
rt_initcols();
|
||||
for (int zz = 4; zz; --zz)
|
||||
{
|
||||
R_WallSpriteColumn(R_DrawMaskedColumnHoriz);
|
||||
if (!R_ClipSpriteColumnWithPortals(spr->gx, spr->gy, spr))
|
||||
R_WallSpriteColumn(R_DrawMaskedColumnHoriz);
|
||||
dc_x++;
|
||||
}
|
||||
rt_draw4cols(dc_x - 4);
|
||||
|
@ -529,7 +573,8 @@ void R_DrawWallSprite(vissprite_t *spr)
|
|||
{ // calculate lighting
|
||||
dc_colormap = usecolormap->Maps + (GETPALOOKUP (rw_light, shade) << COLORMAPSHIFT);
|
||||
}
|
||||
R_WallSpriteColumn(R_DrawMaskedColumn);
|
||||
if (!R_ClipSpriteColumnWithPortals(spr->gx, spr->gy, spr))
|
||||
R_WallSpriteColumn(R_DrawMaskedColumn);
|
||||
dc_x++;
|
||||
}
|
||||
}
|
||||
|
@ -669,6 +714,10 @@ void R_ProjectSprite (AActor *thing, int fakeside, F3DFloor *fakefloor, F3DFloor
|
|||
return;
|
||||
}
|
||||
|
||||
// [ZZ] Or less definitely not visible (hue)
|
||||
if (CurrentPortal && !!P_PointOnLineSide(thing->x, thing->y, CurrentPortal->dst))
|
||||
return;
|
||||
|
||||
// [RH] Interpolate the sprite's position to make it look smooth
|
||||
fx = thing->PrevX + FixedMul (r_TicFrac, thing->x - thing->PrevX);
|
||||
fy = thing->PrevY + FixedMul (r_TicFrac, thing->y - thing->PrevY);
|
||||
|
@ -886,6 +935,7 @@ void R_ProjectSprite (AActor *thing, int fakeside, F3DFloor *fakefloor, F3DFloor
|
|||
// store information in a vissprite
|
||||
vis = R_NewVisSprite();
|
||||
|
||||
vis->CurrentPortalUniq = CurrentPortalUniq;
|
||||
vis->xscale = xscale;
|
||||
vis->yscale = Scale(InvZtoScale, yscale, tz << 4);
|
||||
vis->idepth = (unsigned)DivScale32(1, tz) >> 1; // tz is 20.12, so idepth ought to be 12.20, but signed math makes it 13.19
|
||||
|
@ -913,6 +963,7 @@ void R_ProjectSprite (AActor *thing, int fakeside, F3DFloor *fakefloor, F3DFloor
|
|||
{
|
||||
vis = R_NewVisSprite();
|
||||
|
||||
vis->CurrentPortalUniq = CurrentPortalUniq;
|
||||
vis->xscale = xscale;
|
||||
vis->yscale = yscale;
|
||||
vis->x1 = WindowLeft;
|
||||
|
@ -1074,6 +1125,7 @@ static void R_ProjectWallSprite(AActor *thing, fixed_t fx, fixed_t fy, fixed_t f
|
|||
gzb = fz + yscale * scaled_bo;
|
||||
|
||||
vis = R_NewVisSprite();
|
||||
vis->CurrentPortalUniq = CurrentPortalUniq;
|
||||
vis->x1 = wallc.sx1 < WindowLeft ? WindowLeft : wallc.sx1;
|
||||
vis->x2 = wallc.sx2 >= WindowRight ? WindowRight : wallc.sx2-1;
|
||||
vis->yscale = yscale;
|
||||
|
@ -1774,7 +1826,6 @@ void R_SortVisSprites (bool (*compare)(vissprite_t *, vissprite_t *), size_t fir
|
|||
std::stable_sort(&spritesorter[0], &spritesorter[vsprcount], compare);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// R_DrawSprite
|
||||
//
|
||||
|
@ -2069,8 +2120,11 @@ void R_DrawSprite (vissprite_t *spr)
|
|||
|
||||
for (ds = ds_p; ds-- > firstdrawseg; ) // new -- killough
|
||||
{
|
||||
// [ZZ] portal handling here
|
||||
if (ds->CurrentPortalUniq != spr->CurrentPortalUniq)
|
||||
continue;
|
||||
// kg3D - no clipping on fake segs
|
||||
if(ds->fake) continue;
|
||||
if (ds->fake) continue;
|
||||
// determine if the drawseg obscures the sprite
|
||||
if (ds->x1 > x2 || ds->x2 < x1 ||
|
||||
(!(ds->silhouette & SIL_BOTH) && ds->maskedtexturecol == -1 &&
|
||||
|
@ -2205,6 +2259,8 @@ void R_DrawMaskedSingle (bool renew)
|
|||
|
||||
for (i = vsprcount; i > 0; i--)
|
||||
{
|
||||
if (spritesorter[i-1]->CurrentPortalUniq != CurrentPortalUniq)
|
||||
continue; // probably another time
|
||||
R_DrawSprite (spritesorter[i-1]);
|
||||
}
|
||||
|
||||
|
@ -2222,6 +2278,9 @@ void R_DrawMaskedSingle (bool renew)
|
|||
}
|
||||
for (ds = ds_p; ds-- > firstdrawseg; ) // new -- killough
|
||||
{
|
||||
// [ZZ] the same as above
|
||||
if (ds->CurrentPortalUniq != CurrentPortalUniq)
|
||||
continue;
|
||||
// kg3D - no fake segs
|
||||
if (ds->fake) continue;
|
||||
if (ds->maskedtexturecol != -1 || ds->bFogBoundary)
|
||||
|
@ -2301,6 +2360,10 @@ void R_ProjectParticle (particle_t *particle, const sector_t *sector, int shade,
|
|||
sector_t* heightsec = NULL;
|
||||
BYTE* map;
|
||||
|
||||
// [ZZ] Particle not visible through the portal plane
|
||||
if (CurrentPortal && !!P_PointOnLineSide(particle->x, particle->y, CurrentPortal->dst))
|
||||
return;
|
||||
|
||||
// transform the origin point
|
||||
tr_x = particle->x - viewx;
|
||||
tr_y = particle->y - viewy;
|
||||
|
@ -2404,6 +2467,7 @@ void R_ProjectParticle (particle_t *particle, const sector_t *sector, int shade,
|
|||
|
||||
// store information in a vissprite
|
||||
vis = R_NewVisSprite ();
|
||||
vis->CurrentPortalUniq = CurrentPortalUniq;
|
||||
vis->heightsec = heightsec;
|
||||
vis->xscale = xscale;
|
||||
// vis->yscale = FixedMul (xscale, InvZtoScale);
|
||||
|
@ -2456,8 +2520,11 @@ static void R_DrawMaskedSegsBehindParticle (const vissprite_t *vis)
|
|||
for (unsigned int p = InterestingDrawsegs.Size(); p-- > FirstInterestingDrawseg; )
|
||||
{
|
||||
drawseg_t *ds = &drawsegs[InterestingDrawsegs[p]];
|
||||
// [ZZ] only draw stuff that's inside the same portal as the particle, other portals will care for themselves
|
||||
if (ds->CurrentPortalUniq != vis->CurrentPortalUniq)
|
||||
continue;
|
||||
// kg3D - no fake segs
|
||||
if(ds->fake) continue;
|
||||
if (ds->fake) continue;
|
||||
if (ds->x1 >= x2 || ds->x2 < x1)
|
||||
{
|
||||
continue;
|
||||
|
@ -2495,6 +2562,8 @@ void R_DrawParticle (vissprite_t *vis)
|
|||
fg = fg2rgb[color];
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
spacing = RenderTarget->GetPitch() - countbase;
|
||||
dest = ylookup[yl] + x1 + dc_destorg;
|
||||
|
||||
|
@ -2508,7 +2577,28 @@ void R_DrawParticle (vissprite_t *vis)
|
|||
*dest++ = RGB32k.All[bg & (bg>>15)];
|
||||
} while (--count);
|
||||
dest += spacing;
|
||||
} while (--ycount);
|
||||
} while (--ycount);*/
|
||||
|
||||
// original was row-wise
|
||||
// width = countbase
|
||||
// height = ycount
|
||||
|
||||
spacing = RenderTarget->GetPitch();
|
||||
|
||||
for (int x = x1; x < (x1+countbase); x++)
|
||||
{
|
||||
dc_x = x;
|
||||
if (R_ClipSpriteColumnWithPortals(vis->gx, vis->gy, vis))
|
||||
continue;
|
||||
dest = ylookup[yl] + x + dc_destorg;
|
||||
for (int y = 0; y < ycount; y++)
|
||||
{
|
||||
DWORD bg = bg2rgb[*dest];
|
||||
bg = (fg+bg) | 0x1f07c1f;
|
||||
*dest = RGB32k[0][0][bg & (bg>>15)];
|
||||
dest += spacing;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern fixed_t baseyaspectmul;
|
||||
|
|
|
@ -80,6 +80,7 @@ struct vissprite_t
|
|||
short renderflags;
|
||||
DWORD Translation; // [RH] for color translation
|
||||
visstyle_t Style;
|
||||
int CurrentPortalUniq; // [ZZ] to identify the portal that this thing is in. used for clipping.
|
||||
};
|
||||
|
||||
struct particle_t;
|
||||
|
|
12
zdoom.vcproj
12
zdoom.vcproj
|
@ -6704,6 +6704,18 @@
|
|||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Portals"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\src\portal.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\portal.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
|
|
Loading…
Reference in a new issue