gzdoom-gles/src/r_defs.h

1577 lines
36 KiB
C
Raw Normal View History

2016-03-01 15:47:10 +00:00
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// $Id:$
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This source is available for distribution and/or modification
// only under the terms of the DOOM Source Code License as
// published by id Software. All rights reserved.
//
// The source is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
// for more details.
//
// DESCRIPTION:
// Refresh/rendering module, shared data struct definitions.
//
//-----------------------------------------------------------------------------
#ifndef __R_DEFS_H__
#define __R_DEFS_H__
#include "doomdef.h"
#include "templates.h"
#include "memarena.h"
#include "m_bbox.h"
2016-03-01 15:47:10 +00:00
// Some more or less basic data types
// we depend on.
#include "m_fixed.h"
// We rely on the thinker data struct
// to handle sound origins in sectors.
// SECTORS do store MObjs anyway.
#include "actor.h"
struct FLightNode;
struct FGLSection;
struct FPortal;
struct seg_t;
2016-03-01 15:47:10 +00:00
#include "dthinker.h"
#define MAXWIDTH 5760
#define MAXHEIGHT 3600
const WORD NO_INDEX = 0xffffu;
const DWORD NO_SIDE = 0xffffffffu;
// Silhouette, needed for clipping Segs (mainly)
// and sprites representing things.
enum
{
SIL_NONE,
SIL_BOTTOM,
SIL_TOP,
SIL_BOTH
};
namespace swrenderer { extern size_t MaxDrawSegs; }
2016-03-01 15:47:10 +00:00
struct FDisplacement;
//
// INTERNAL MAP TYPES
// used by play and refresh
//
//
// Your plain vanilla vertex.
// Note: transformed values not buffered locally,
// like some DOOM-alikes ("wt", "WebView") did.
//
enum
{
VERTEXFLAG_ZCeilingEnabled = 0x01,
VERTEXFLAG_ZFloorEnabled = 0x02
};
struct vertexdata_t
{
double zCeiling, zFloor;
2016-03-01 15:47:10 +00:00
DWORD flags;
};
#ifdef USE_FLOAT
typedef float vtype;
#elif !defined USE_FIXED
typedef double vtype;
#endif
2016-03-01 15:47:10 +00:00
struct vertex_t
{
private:
DVector2 p;
2016-03-01 15:47:10 +00:00
public:
void set(fixed_t x, fixed_t y)
{
p.X = x / 65536.;
p.Y = y / 65536.;
}
void set(double x, double y)
{
p.X = x;
p.Y = y;
}
void set(const DVector2 &pos)
{
p = pos;
}
2016-03-22 21:07:38 +00:00
double fX() const
{
return p.X;
2016-03-22 21:07:38 +00:00
}
double fY() const
{
return p.Y;
2016-03-22 21:07:38 +00:00
}
fixed_t fixX() const
{
return FLOAT2FIXED(p.X);
}
fixed_t fixY() const
{
return FLOAT2FIXED(p.Y);
}
DVector2 fPos()
{
return { p.X, p.Y };
}
angle_t viewangle; // precalculated angle for clipping
int angletime; // recalculation time for view angle
bool dirty; // something has changed and needs to be recalculated
int numheights;
int numsectors;
sector_t ** sectors;
float * heightlist;
vertex_t()
{
p = { 0,0 };
angletime = 0;
viewangle = 0;
dirty = true;
numheights = numsectors = 0;
sectors = NULL;
heightlist = NULL;
}
2016-03-01 15:47:10 +00:00
bool operator== (const vertex_t &other)
{
return p == other.p;
}
bool operator!= (const vertex_t &other)
{
return p != other.p;
2016-03-01 15:47:10 +00:00
}
void clear()
{
p.Zero();
2016-03-01 15:47:10 +00:00
}
angle_t GetClipAngle();
2016-03-01 15:47:10 +00:00
};
// Forward of LineDefs, for Sectors.
struct line_t;
class player_t;
class FScanner;
class FBitmap;
struct FCopyInfo;
class DInterpolation;
enum
{
UDMF_Line,
UDMF_Side,
UDMF_Sector,
UDMF_Thing
};
struct FUDMFKey
{
enum
{
UDMF_Int,
UDMF_Float,
UDMF_String
};
FName Key;
int Type;
int IntVal;
double FloatVal;
FString StringVal;
FUDMFKey()
{
}
FUDMFKey& operator =(int val)
{
Type = UDMF_Int;
IntVal = val;
FloatVal = val;
StringVal = "";
return *this;
}
FUDMFKey& operator =(double val)
{
Type = UDMF_Float;
IntVal = int(val);
FloatVal = val;
StringVal = "";
return *this;
}
FUDMFKey& operator =(const FString &val)
{
Type = UDMF_String;
IntVal = strtol(val.GetChars(), NULL, 0);
FloatVal = strtod(val.GetChars(), NULL);
StringVal = val;
return *this;
}
};
class FUDMFKeys : public TArray<FUDMFKey>
{
bool mSorted = false;
2016-03-01 15:47:10 +00:00
public:
void Sort();
FUDMFKey *Find(FName key);
};
//
// The SECTORS record, at runtime.
// Stores things/mobjs.
//
class DSectorEffect;
struct sector_t;
struct FRemapTable;
enum
{
SECSPAC_Enter = 1, // Trigger when player enters
SECSPAC_Exit = 2, // Trigger when player exits
SECSPAC_HitFloor = 4, // Trigger when player hits floor
SECSPAC_HitCeiling = 8, // Trigger when player hits ceiling
SECSPAC_Use = 16, // Trigger when player uses
SECSPAC_UseWall = 32, // Trigger when player uses a wall
SECSPAC_EyesDive = 64, // Trigger when player eyes go below fake floor
SECSPAC_EyesSurface = 128, // Trigger when player eyes go above fake floor
SECSPAC_EyesBelowC = 256, // Trigger when player eyes go below fake ceiling
SECSPAC_EyesAboveC = 512, // Trigger when player eyes go above fake ceiling
SECSPAC_HitFakeFloor= 1024, // Trigger when player hits fake floor
};
class ASectorAction : public AActor
{
DECLARE_CLASS (ASectorAction, AActor)
public:
ASectorAction (bool activatedByUse = false);
void Destroy ();
void BeginPlay ();
void Activate (AActor *source);
void Deactivate (AActor *source);
bool TriggerAction(AActor *triggerer, int activationType);
bool CanTrigger (AActor *triggerer) const;
bool IsActivatedByUse() const;
protected:
virtual bool DoTriggerAction(AActor *triggerer, int activationType);
bool CheckTrigger(AActor *triggerer) const;
private:
bool ActivatedByUse;
};
class ASkyViewpoint;
struct secplane_t
{
// the plane is defined as a*x + b*y + c*z + d = 0
// ic is 1/c, for faster Z calculations
//private:
DVector3 normal;
double D, negiC; // negative iC because that also saves a negation in all methods using this.
public:
friend FSerializer &Serialize(FSerializer &arc, const char *key, secplane_t &p, secplane_t *def);
void set(double aa, double bb, double cc, double dd)
{
normal.X = aa;
normal.Y = bb;
normal.Z = cc;
D = dd;
negiC = -1 / cc;
}
void setD(double dd)
{
D = dd;
}
double fC() const
{
return normal.Z;
}
double fD() const
{
return D;
}
2016-03-26 22:19:38 +00:00
bool isSlope() const
{
return !normal.XY().isZero();
2016-03-26 22:19:38 +00:00
}
DVector3 Normal() const
{
return normal;
}
2016-03-01 15:47:10 +00:00
// Returns < 0 : behind; == 0 : on; > 0 : in front
int PointOnSide(const DVector3 &pos) const
{
double v = (normal | pos) + D;
return v < -EQUAL_EPSILON ? -1 : v > EQUAL_EPSILON ? 1 : 0;
}
2016-03-01 15:47:10 +00:00
// Returns the value of z at (0,0) This is used by the 3D floor code which does not handle slopes
2016-04-14 17:40:14 +00:00
double Zat0() const
2016-03-01 15:47:10 +00:00
{
2016-04-14 17:40:14 +00:00
return negiC*D;
2016-03-01 15:47:10 +00:00
}
// Returns the value of z at (x,y)
fixed_t ZatPoint(fixed_t x, fixed_t y) const = delete; // it is not allowed to call this.
2016-03-01 15:47:10 +00:00
// Returns the value of z at (x,y) as a double
double ZatPoint (double x, double y) const
{
return (D + normal.X*x + normal.Y*y) * negiC;
2016-03-01 15:47:10 +00:00
}
double ZatPoint(const DVector2 &pos) const
{
return (D + normal.X*pos.X + normal.Y*pos.Y) * negiC;
}
2016-04-14 17:40:14 +00:00
double ZatPoint(const FVector2 &pos) const
{
return (D + normal.X*pos.X + normal.Y*pos.Y) * negiC;
}
double ZatPoint(const vertex_t *v) const
{
return (D + normal.X*v->fX() + normal.Y*v->fY()) * negiC;
}
double ZatPoint(const AActor *ac) const
{
return (D + normal.X*ac->X() + normal.Y*ac->Y()) * negiC;
}
2016-03-01 15:47:10 +00:00
// Returns the value of z at vertex v if d is equal to dist
double ZatPointDist(const vertex_t *v, double dist)
2016-03-01 15:47:10 +00:00
{
return (dist + normal.X*v->fX() + normal.Y*v->fY()) * negiC;
2016-03-01 15:47:10 +00:00
}
// Flips the plane's vertical orientiation, so that if it pointed up,
// it will point down, and vice versa.
void FlipVert ()
{
normal = -normal;
D = -D;
negiC = -negiC;
2016-03-01 15:47:10 +00:00
}
// Returns true if 2 planes are the same
bool operator== (const secplane_t &other) const
{
return normal == other.normal && D == other.D;
2016-03-01 15:47:10 +00:00
}
// Returns true if 2 planes are different
bool operator!= (const secplane_t &other) const
{
return normal != other.normal || D != other.D;
2016-03-01 15:47:10 +00:00
}
// Moves a plane up/down by hdiff units
void ChangeHeight(double hdiff)
2016-03-01 15:47:10 +00:00
{
D = D - hdiff * normal.Z;
2016-03-01 15:47:10 +00:00
}
// Moves a plane up/down by hdiff units
double GetChangedHeight(double hdiff)
2016-03-01 15:47:10 +00:00
{
return D - hdiff * normal.Z;
2016-03-01 15:47:10 +00:00
}
// Returns how much this plane's height would change if d were set to oldd
double HeightDiff(double oldd) const
2016-03-01 15:47:10 +00:00
{
return (D - oldd) * negiC;
}
// Returns how much this plane's height would change if d were set to oldd
double HeightDiff(double oldd, double newd) const
{
return (newd - oldd) * negiC;
2016-03-01 15:47:10 +00:00
}
double PointToDist(const DVector2 &xy, double z) const
{
return -(normal.X * xy.X + normal.Y * xy.Y + normal.Z * z);
}
double PointToDist(const vertex_t *v, double z) const
{
return -(normal.X * v->fX() + normal.Y * v->fY() + normal.Z * z);
}
void SetAtHeight(double height, int ceiling)
2016-03-01 15:47:10 +00:00
{
normal.X = normal.Y = 0;
2016-03-01 15:47:10 +00:00
if (ceiling)
{
normal.Z = -1;
negiC = 1;
D = height;
2016-03-01 15:47:10 +00:00
}
else
{
normal.Z = 1;
negiC = -1;
D = -height;
2016-03-01 15:47:10 +00:00
}
}
bool CopyPlaneIfValid (secplane_t *dest, const secplane_t *opp) const;
};
#include "p_3dfloors.h"
struct subsector_t;
struct sector_t;
struct side_t;
extern bool gl_plane_reflection_i;
2016-03-01 15:47:10 +00:00
// Ceiling/floor flags
enum
{
PLANEF_ABSLIGHTING = 1, // floor/ceiling light is absolute, not relative
PLANEF_BLOCKED = 2, // can not be moved anymore.
PLANEF_ADDITIVE = 4, // rendered additive
// linked portal stuff
PLANEF_NORENDER = 8,
PLANEF_NOPASS = 16,
PLANEF_BLOCKSOUND = 32,
PLANEF_DISABLED = 64,
PLANEF_OBSTRUCTED = 128, // if the portal plane is beyond the sector's floor or ceiling.
PLANEF_LINKED = 256 // plane is flagged as a linked portal
2016-03-01 15:47:10 +00:00
};
// Internal sector flags
enum
{
SECF_FAKEFLOORONLY = 2, // when used as heightsec in R_FakeFlat, only copies floor
SECF_CLIPFAKEPLANES = 4, // as a heightsec, clip planes to target sector's planes
SECF_NOFAKELIGHT = 8, // heightsec does not change lighting
SECF_IGNOREHEIGHTSEC= 16, // heightsec is only for triggering sector actions
SECF_UNDERWATER = 32, // sector is underwater
SECF_FORCEDUNDERWATER= 64, // sector is forced to be underwater
SECF_UNDERWATERMASK = 32+64,
SECF_DRAWN = 128, // sector has been drawn at least once
SECF_HIDDEN = 256, // Do not draw on textured automap
};
enum
{
SECF_SILENT = 1, // actors in sector make no noise
SECF_NOFALLINGDAMAGE= 2, // No falling damage in this sector
SECF_FLOORDROP = 4, // all actors standing on this floor will remain on it when it lowers very fast.
SECF_NORESPAWN = 8, // players can not respawn in this sector
SECF_FRICTION = 16, // sector has friction enabled
SECF_PUSH = 32, // pushers enabled
SECF_SILENTMOVE = 64, // Sector movement makes mo sound (Eternity got this so this may be useful for an extended cross-port standard.)
SECF_DMGTERRAINFX = 128, // spawns terrain splash when inflicting damage
SECF_ENDGODMODE = 256, // getting damaged by this sector ends god mode
SECF_ENDLEVEL = 512, // ends level when health goes below 10
SECF_HAZARD = 1024, // Change to Strife's delayed damage handling.
SECF_WASSECRET = 1 << 30, // a secret that was discovered
SECF_SECRET = 1 << 31, // a secret sector
SECF_DAMAGEFLAGS = SECF_ENDGODMODE|SECF_ENDLEVEL|SECF_DMGTERRAINFX|SECF_HAZARD,
SECF_NOMODIFY = SECF_SECRET|SECF_WASSECRET, // not modifiable by Sector_ChangeFlags
SECF_SPECIALFLAGS = SECF_DAMAGEFLAGS|SECF_FRICTION|SECF_PUSH, // these flags originate from 'special and must be transferrable by floor thinkers
};
enum
{
PL_SKYFLAT = 0x40000000
};
struct FDynamicColormap;
struct FLinkedSector
{
sector_t *Sector;
int Type;
};
// this substructure contains a few sector properties that are stored in dynamic arrays
// These must not be copied by R_FakeFlat etc. or bad things will happen.
struct extsector_t
{
// Boom sector transfer information
struct fakefloor
{
TArray<sector_t *> Sectors;
} FakeFloor;
// 3DMIDTEX information
struct midtex
{
struct plane
{
TArray<sector_t *> AttachedSectors; // all sectors containing 3dMidtex lines attached to this sector
TArray<line_t *> AttachedLines; // all 3dMidtex lines attached to this sector
} Floor, Ceiling;
} Midtex;
// Linked sector information
struct linked
{
struct plane
{
TArray<FLinkedSector> Sectors;
} Floor, Ceiling;
} Linked;
// 3D floors
struct xfloor
{
TDeletingArray<F3DFloor *> ffloors; // 3D floors in this sector
TArray<lightlist_t> lightlist; // 3D light list
TArray<sector_t*> attached; // 3D floors attached to this sector
} XFloor;
TArray<vertex_t *> vertices;
2016-03-01 15:47:10 +00:00
};
struct FTransform
{
// killough 3/7/98: floor and ceiling texture offsets
double xOffs, yOffs, baseyOffs;
2016-03-01 15:47:10 +00:00
// [RH] floor and ceiling texture scales
double xScale, yScale;
2016-03-01 15:47:10 +00:00
// [RH] floor and ceiling texture rotation
DAngle Angle, baseAngle;
finline bool operator == (const FTransform &other) const
{
return xOffs == other.xOffs && yOffs + baseyOffs == other.yOffs + other.baseyOffs &&
xScale == other.xScale && yScale == other.yScale && Angle + baseAngle == other.Angle + other.baseAngle;
}
finline bool operator != (const FTransform &other) const
{
return !(*this == other);
}
2016-03-01 15:47:10 +00:00
};
struct secspecial_t
{
FNameNoInit damagetype; // [RH] Means-of-death for applied damage
int damageamount; // [RH] Damage to do while standing on floor
short special;
short damageinterval; // Interval for damage application
short leakydamage; // chance of leaking through radiation suit
int Flags;
secspecial_t()
{
Clear();
}
void Clear()
{
memset(this, 0, sizeof(*this));
}
};
FSerializer &Serialize(FSerializer &arc, const char *key, secspecial_t &spec, secspecial_t *def);
2016-03-01 15:47:10 +00:00
enum class EMoveResult { ok, crushed, pastdest };
2016-03-01 15:47:10 +00:00
struct sector_t
{
// Member functions
private:
bool MoveAttached(int crush, double move, int floorOrCeiling, bool resetfailed);
public:
EMoveResult MoveFloor(double speed, double dest, int crush, int direction, bool hexencrush);
EMoveResult MoveCeiling(double speed, double dest, int crush, int direction, bool hexencrush);
inline EMoveResult MoveFloor(double speed, double dest, int direction)
{
return MoveFloor(speed, dest, -1, direction, false);
}
inline EMoveResult MoveCeiling(double speed, double dest, int direction)
{
return MoveCeiling(speed, dest, -1, direction, false);
}
2016-03-01 15:47:10 +00:00
bool IsLinked(sector_t *other, bool ceiling) const;
double FindLowestFloorSurrounding(vertex_t **v) const;
double FindHighestFloorSurrounding(vertex_t **v) const;
double FindNextHighestFloor(vertex_t **v) const;
double FindNextLowestFloor(vertex_t **v) const;
double FindLowestCeilingSurrounding(vertex_t **v) const; // jff 2/04/98
double FindHighestCeilingSurrounding(vertex_t **v) const; // jff 2/04/98
double FindNextLowestCeiling(vertex_t **v) const; // jff 2/04/98
double FindNextHighestCeiling(vertex_t **v) const; // jff 2/04/98
double FindShortestTextureAround() const; // jff 2/04/98
double FindShortestUpperAround() const; // jff 2/04/98
sector_t *FindModelFloorSector(double floordestheight) const; // jff 2/04/98
sector_t *FindModelCeilingSector(double floordestheight) const; // jff 2/04/98
2016-03-01 15:47:10 +00:00
int FindMinSurroundingLight (int max) const;
sector_t *NextSpecialSector (int type, sector_t *prev) const; // [RH]
double FindLowestCeilingPoint(vertex_t **v) const;
double FindHighestFloorPoint(vertex_t **v) const;
2016-03-01 15:47:10 +00:00
void AdjustFloorClip () const;
void SetColor(int r, int g, int b, int desat);
void SetFade(int r, int g, int b);
void ClosestPoint(const DVector2 &pos, DVector2 &out) const;
2016-03-01 15:47:10 +00:00
int GetFloorLight () const;
int GetCeilingLight () const;
sector_t *GetHeightSec() const;
2016-03-24 21:50:03 +00:00
double GetFriction(int plane = sector_t::floor, double *movefac = NULL) const;
2016-03-01 15:47:10 +00:00
DInterpolation *SetInterpolation(int position, bool attach);
FSectorPortal *ValidatePortal(int which);
2016-03-01 15:47:10 +00:00
void CheckPortalPlane(int plane);
enum
{
floor,
ceiling
};
struct splane
{
FTransform xform;
int Flags;
int Light;
double alpha;
2016-03-01 15:47:10 +00:00
FTextureID Texture;
double TexZ;
2016-03-01 15:47:10 +00:00
};
splane planes[2];
void SetXOffset(int pos, double o)
{
planes[pos].xform.xOffs = o;
}
void AddXOffset(int pos, double o)
{
planes[pos].xform.xOffs += o;
2016-03-01 15:47:10 +00:00
}
2016-04-23 11:40:02 +00:00
double GetXOffset(int pos) const
2016-03-25 20:54:59 +00:00
{
return planes[pos].xform.xOffs;
2016-03-25 20:54:59 +00:00
}
void SetYOffset(int pos, double o)
{
planes[pos].xform.yOffs = o;
}
void AddYOffset(int pos, double o)
{
planes[pos].xform.yOffs += o;
2016-03-01 15:47:10 +00:00
}
2016-04-23 11:40:02 +00:00
double GetYOffset(int pos, bool addbase = true) const
2016-03-25 20:54:59 +00:00
{
if (!addbase)
{
return planes[pos].xform.yOffs;
2016-03-25 20:54:59 +00:00
}
else
{
return planes[pos].xform.yOffs + planes[pos].xform.baseyOffs;
2016-03-25 20:54:59 +00:00
}
}
void SetXScale(int pos, double o)
{
planes[pos].xform.xScale = o;
2016-03-01 15:47:10 +00:00
}
2016-04-23 11:40:02 +00:00
double GetXScale(int pos) const
2016-03-25 20:54:59 +00:00
{
return planes[pos].xform.xScale;
2016-03-25 20:54:59 +00:00
}
void SetYScale(int pos, double o)
{
planes[pos].xform.yScale = o;
2016-03-01 15:47:10 +00:00
}
2016-04-23 11:40:02 +00:00
double GetYScale(int pos) const
2016-03-25 20:54:59 +00:00
{
return planes[pos].xform.yScale;
2016-03-25 20:54:59 +00:00
}
void SetAngle(int pos, DAngle o)
{
planes[pos].xform.Angle = o;
2016-03-01 15:47:10 +00:00
}
2016-04-23 11:40:02 +00:00
DAngle GetAngle(int pos, bool addbase = true) const
2016-03-25 20:54:59 +00:00
{
if (!addbase)
{
return planes[pos].xform.Angle;
2016-03-25 20:54:59 +00:00
}
else
{
return planes[pos].xform.Angle + planes[pos].xform.baseAngle;
2016-03-25 20:54:59 +00:00
}
}
void SetBase(int pos, double y, DAngle o)
2016-03-01 15:47:10 +00:00
{
planes[pos].xform.baseyOffs = y;
planes[pos].xform.baseAngle = o;
2016-03-01 15:47:10 +00:00
}
void SetAlpha(int pos, double o)
{
planes[pos].alpha = o;
}
double GetAlpha(int pos) const
2016-03-01 15:47:10 +00:00
{
return planes[pos].alpha;
}
int GetFlags(int pos) const
2016-03-01 15:47:10 +00:00
{
return planes[pos].Flags;
}
// like the previous one but masks out all flags which are not relevant for rendering.
int GetVisFlags(int pos) const
{
return planes[pos].Flags & ~(PLANEF_BLOCKED | PLANEF_NOPASS | PLANEF_BLOCKSOUND | PLANEF_LINKED);
}
2016-03-01 15:47:10 +00:00
void ChangeFlags(int pos, int And, int Or)
{
planes[pos].Flags &= ~And;
planes[pos].Flags |= Or;
}
int GetPlaneLight(int pos) const
{
return planes[pos].Light;
}
void SetPlaneLight(int pos, int level)
{
planes[pos].Light = level;
}
FTextureID GetTexture(int pos) const
{
return planes[pos].Texture;
}
void SetTexture(int pos, FTextureID tex, bool floorclip = true)
{
FTextureID old = planes[pos].Texture;
planes[pos].Texture = tex;
if (floorclip && pos == floor && tex != old) AdjustFloorClip();
}
double GetPlaneTexZ(int pos) const
2016-03-01 15:47:10 +00:00
{
return planes[pos].TexZ;
}
2016-03-30 18:01:44 +00:00
void SetPlaneTexZ(int pos, double val, bool dirtify = false) // This mainly gets used by init code. The only place where it must set the vertex to dirty is the interpolation code.
{
planes[pos].TexZ = val;
2016-03-30 18:01:44 +00:00
if (dirtify) SetAllVerticesDirty();
}
void ChangePlaneTexZ(int pos, double val)
{
planes[pos].TexZ += val;
}
2016-03-01 15:47:10 +00:00
static inline short ClampLight(int level)
{
return (short)clamp(level, SHRT_MIN, SHRT_MAX);
}
void ChangeLightLevel(int newval)
{
lightlevel = ClampLight(lightlevel + newval);
}
void SetLightLevel(int newval)
{
lightlevel = ClampLight(newval);
}
int GetLightLevel() const
{
return lightlevel;
}
secplane_t &GetSecPlane(int pos)
{
return pos == floor? floorplane:ceilingplane;
}
bool isSecret() const
{
return !!(Flags & SECF_SECRET);
}
bool wasSecret() const
{
return !!(Flags & SECF_WASSECRET);
}
void ClearSecret()
{
Flags &= ~SECF_SECRET;
}
void ClearSpecial()
{
// clears all variables that originate from 'special'. Used for sector type transferring thinkers
special = 0;
damageamount = 0;
damageinterval = 0;
damagetype = NAME_None;
leakydamage = 0;
Flags &= ~SECF_SPECIALFLAGS;
}
bool PortalBlocksView(int plane)
{
if (GetPortalType(plane) != PORTS_LINKEDPORTAL) return false;
2016-03-01 15:47:10 +00:00
return !!(planes[plane].Flags & (PLANEF_NORENDER | PLANEF_DISABLED | PLANEF_OBSTRUCTED));
}
bool PortalBlocksSight(int plane)
{
return PLANEF_LINKED != (planes[plane].Flags & (PLANEF_NORENDER | PLANEF_NOPASS | PLANEF_DISABLED | PLANEF_OBSTRUCTED | PLANEF_LINKED));
2016-03-01 15:47:10 +00:00
}
bool PortalBlocksMovement(int plane)
{
return PLANEF_LINKED != (planes[plane].Flags & (PLANEF_NOPASS | PLANEF_DISABLED | PLANEF_OBSTRUCTED | PLANEF_LINKED));
2016-03-01 15:47:10 +00:00
}
bool PortalBlocksSound(int plane)
{
return PLANEF_LINKED != (planes[plane].Flags & (PLANEF_BLOCKSOUND | PLANEF_DISABLED | PLANEF_OBSTRUCTED | PLANEF_LINKED));
2016-03-01 15:47:10 +00:00
}
bool PortalIsLinked(int plane)
{
return (GetPortalType(plane) == PORTS_LINKEDPORTAL);
}
void ClearPortal(int plane)
{
Portals[plane] = 0;
portals[plane] = nullptr;
}
FSectorPortal *GetPortal(int plane)
{
return &sectorPortals[Portals[plane]];
}
double GetPortalPlaneZ(int plane)
{
return sectorPortals[Portals[plane]].mPlaneZ;
}
DVector2 GetPortalDisplacement(int plane)
{
return sectorPortals[Portals[plane]].mDisplacement;
}
int GetPortalType(int plane)
{
return sectorPortals[Portals[plane]].mType;
}
int GetOppositePortalGroup(int plane)
{
return sectorPortals[Portals[plane]].mDestination->PortalGroup;
}
void SetVerticesDirty()
{
for (unsigned i = 0; i < e->vertices.Size(); i++) e->vertices[i]->dirty = true;
}
void SetAllVerticesDirty()
{
SetVerticesDirty();
for (unsigned i = 0; i < e->FakeFloor.Sectors.Size(); i++) e->FakeFloor.Sectors[i]->SetVerticesDirty();
for (unsigned i = 0; i < e->XFloor.attached.Size(); i++) e->XFloor.attached[i]->SetVerticesDirty();
}
2016-03-01 15:47:10 +00:00
int GetTerrain(int pos) const;
void TransferSpecial(sector_t *model);
void GetSpecial(secspecial_t *spec);
void SetSpecial(const secspecial_t *spec);
bool PlaneMoving(int pos);
// Portal-aware height calculation
double HighestCeilingAt(const DVector2 &a, sector_t **resultsec = NULL);
double LowestFloorAt(const DVector2 &a, sector_t **resultsec = NULL);
2016-03-01 15:47:10 +00:00
double HighestCeilingAt(AActor *a, sector_t **resultsec = NULL)
2016-03-01 15:47:10 +00:00
{
return HighestCeilingAt(a->Pos(), resultsec);
}
double LowestFloorAt(AActor *a, sector_t **resultsec = NULL)
{
return LowestFloorAt(a->Pos(), resultsec);
2016-03-01 15:47:10 +00:00
}
double NextHighestCeilingAt(double x, double y, double bottomz, double topz, int flags = 0, sector_t **resultsec = NULL, F3DFloor **resultffloor = NULL);
double NextLowestFloorAt(double x, double y, double z, int flags = 0, double steph = 0, sector_t **resultsec = NULL, F3DFloor **resultffloor = NULL);
2016-03-01 15:47:10 +00:00
// Member variables
double CenterFloor() const { return floorplane.ZatPoint(centerspot); }
double CenterCeiling() const { return ceilingplane.ZatPoint(centerspot); }
2016-03-01 15:47:10 +00:00
// [RH] store floor and ceiling planes instead of heights
secplane_t floorplane, ceilingplane;
// [RH] give floor and ceiling even more properties
FDynamicColormap *ColorMap; // [RH] Per-sector colormap
TObjPtr<AActor> SoundTarget;
short special;
short lightlevel;
short seqType; // this sector's sound sequence
int sky;
FNameNoInit SeqName; // Sound sequence name. Setting seqType non-negative will override this.
DVector2 centerspot; // origin for any sounds played by the sector
2016-03-01 15:47:10 +00:00
int validcount; // if == validcount, already checked
AActor* thinglist; // list of mobjs in sector
// killough 8/28/98: friction is a sector property, not an mobj property.
// these fields used to be in AActor, but presented performance problems
// when processed as mobj properties. Fix is to make them sector properties.
2016-03-24 21:50:03 +00:00
double friction, movefactor;
2016-03-01 15:47:10 +00:00
int terrainnum[2];
// thinker_t for reversable actions
TObjPtr<DSectorEffect> floordata; // jff 2/22/98 make thinkers on
TObjPtr<DSectorEffect> ceilingdata; // floors, ceilings, lighting,
TObjPtr<DSectorEffect> lightingdata; // independent of one another
enum
{
CeilingMove,
FloorMove,
CeilingScroll,
FloorScroll
};
TObjPtr<DInterpolation> interpolations[4];
BYTE soundtraversed; // 0 = untraversed, 1,2 = sndlines -1
// jff 2/26/98 lockout machinery for stairbuilding
SBYTE stairlock; // -2 on first locked -1 after thinker done 0 normally
SWORD prevsec; // -1 or number of sector for previous step
SWORD nextsec; // -1 or number of next step sector
short linecount;
struct line_t **lines; // [linecount] size
// killough 3/7/98: support flat heights drawn at another sector's heights
sector_t *heightsec; // other sector, or NULL if no other sector
DWORD bottommap, midmap, topmap; // killough 4/4/98: dynamic colormaps
// [RH] these can also be blend values if
// the alpha mask is non-zero
// list of mobjs that are at least partially in the sector
// thinglist is a subset of touching_thinglist
struct msecnode_t *touching_thinglist; // phares 3/14/98
struct msecnode_t *render_thinglist; // for cross-portal rendering.
2016-03-01 15:47:10 +00:00
double gravity; // [RH] Sector gravity (1.0 is normal)
2016-03-01 15:47:10 +00:00
FNameNoInit damagetype; // [RH] Means-of-death for applied damage
int damageamount; // [RH] Damage to do while standing on floor
short damageinterval; // Interval for damage application
short leakydamage; // chance of leaking through radiation suit
WORD ZoneNumber; // [RH] Zone this sector belongs to
WORD MoreFlags; // [RH] Internal sector flags
DWORD Flags; // Sector flags
// [RH] Action specials for sectors. Like Skull Tag, but more
// flexible in a Bloody way. SecActTarget forms a list of actors
// joined by their tracer fields. When a potential sector action
// occurs, SecActTarget's TriggerAction method is called.
TObjPtr<ASectorAction> SecActTarget;
// [RH] The portal or skybox to render for this sector.
unsigned Portals[2];
2016-03-01 15:47:10 +00:00
int PortalGroup;
int sectornum; // for comparing sector copies
extsector_t * e; // This stores data that requires construction/destruction. Such data must not be copied by R_FakeFlat.
// GL only stuff starts here
float reflect[2];
bool transdoor; // For transparent door hacks
int subsectorcount; // list of subsectors
2016-04-24 11:35:43 +00:00
double transdoorheight; // for transparent door hacks
subsector_t ** subsectors;
FPortal * portals[2]; // floor and ceiling portals
FLightNode * lighthead;
enum
{
vbo_fakefloor = floor+2,
vbo_fakeceiling = ceiling+2,
};
int vboindex[4]; // VBO indices of the 4 planes this sector uses during rendering
2016-04-24 11:35:43 +00:00
double vboheight[2]; // Last calculated height for the 2 planes of this actual sector
int vbocount[2]; // Total count of vertices belonging to this sector's planes
float GetReflect(int pos) { return gl_plane_reflection_i? reflect[pos] : 0; }
bool VBOHeightcheck(int pos) const { return vboheight[pos] == GetPlaneTexZ(pos); }
FPortal *GetGLPortal(int plane) { return portals[plane]; }
enum
{
INVALIDATE_PLANES = 1,
INVALIDATE_OTHER = 2
};
2016-03-01 15:47:10 +00:00
};
struct ReverbContainer;
struct zone_t
{
ReverbContainer *Environment;
};
//
// The SideDef.
//
class DBaseDecal;
enum
{
WALLF_ABSLIGHTING = 1, // Light is absolute instead of relative
WALLF_NOAUTODECALS = 2, // Do not attach impact decals to this wall
WALLF_NOFAKECONTRAST = 4, // Don't do fake contrast for this wall in side_t::GetLightLevel
WALLF_SMOOTHLIGHTING = 8, // Similar to autocontrast but applies to all angles.
WALLF_CLIP_MIDTEX = 16, // Like the line counterpart, but only for this side.
WALLF_WRAP_MIDTEX = 32, // Like the line counterpart, but only for this side.
WALLF_POLYOBJ = 64, // This wall belongs to a polyobject.
WALLF_LIGHT_FOG = 128, // This wall's Light is used even in fog.
};
struct side_t
{
enum ETexpart
{
top=0,
mid=1,
bottom=2
};
struct part
{
double xOffset;
double yOffset;
double xScale;
double yScale;
2016-03-01 15:47:10 +00:00
FTextureID texture;
TObjPtr<DInterpolation> interpolation;
//int Light;
};
sector_t* sector; // Sector the SideDef is facing.
DBaseDecal* AttachedDecals; // [RH] Decals bound to the wall
part textures[3];
line_t *linedef;
//DWORD linenum;
DWORD LeftSide, RightSide; // [RH] Group walls into loops
WORD TexelLength;
SWORD Light;
BYTE Flags;
int Index; // needed to access custom UDMF fields which are stored in loading order.
int GetLightLevel (bool foggy, int baselight, bool is3dlight=false, int *pfakecontrast_usedbygzdoom=NULL) const;
void SetLight(SWORD l)
{
Light = l;
}
FTextureID GetTexture(int which) const
{
return textures[which].texture;
}
void SetTexture(int which, FTextureID tex)
{
textures[which].texture = tex;
}
void SetTextureXOffset(int which, double offset)
{
textures[which].xOffset = offset;;
}
void SetTextureXOffset(double offset)
{
textures[top].xOffset =
textures[mid].xOffset =
textures[bottom].xOffset = offset;
2016-03-01 15:47:10 +00:00
}
double GetTextureXOffset(int which) const
{
return textures[which].xOffset;
2016-03-01 15:47:10 +00:00
}
void AddTextureXOffset(int which, double delta)
{
textures[which].xOffset += delta;
}
2016-03-01 15:47:10 +00:00
void SetTextureYOffset(int which, double offset)
{
textures[which].yOffset = offset;
}
void SetTextureYOffset(double offset)
{
textures[top].yOffset =
textures[mid].yOffset =
textures[bottom].yOffset = offset;
2016-03-01 15:47:10 +00:00
}
double GetTextureYOffset(int which) const
{
return textures[which].yOffset;
2016-03-01 15:47:10 +00:00
}
void AddTextureYOffset(int which, double delta)
{
textures[which].yOffset += delta;
}
2016-03-01 15:47:10 +00:00
void SetTextureXScale(int which, double scale)
{
textures[which].xScale = scale == 0 ? 1. : scale;
2016-03-01 15:47:10 +00:00
}
void SetTextureXScale(double scale)
{
textures[top].xScale = textures[mid].xScale = textures[bottom].xScale = scale == 0 ? 1. : scale;
2016-03-01 15:47:10 +00:00
}
double GetTextureXScale(int which) const
2016-03-01 15:47:10 +00:00
{
return textures[which].xScale;
2016-03-01 15:47:10 +00:00
}
void MultiplyTextureXScale(int which, double delta)
2016-03-01 15:47:10 +00:00
{
textures[which].xScale *= delta;
2016-03-01 15:47:10 +00:00
}
void SetTextureYScale(int which, double scale)
{
textures[which].yScale = scale == 0 ? 1. : scale;
}
void SetTextureYScale(double scale)
{
textures[top].yScale = textures[mid].yScale = textures[bottom].yScale = scale == 0 ? 1. : scale;
2016-03-01 15:47:10 +00:00
}
double GetTextureYScale(int which) const
{
return textures[which].yScale;
}
void MultiplyTextureYScale(int which, double delta)
2016-03-01 15:47:10 +00:00
{
textures[which].yScale *= delta;
2016-03-01 15:47:10 +00:00
}
DInterpolation *SetInterpolation(int position);
void StopInterpolation(int position);
vertex_t *V1() const;
vertex_t *V2() const;
//For GL
FLightNode * lighthead; // all blended lights that may affect this wall
seg_t **segs; // all segs belonging to this sidedef in ascending order. Used for precise rendering
int numsegs;
2016-03-01 15:47:10 +00:00
};
struct line_t
{
vertex_t *v1, *v2; // vertices, from v1 to v2
private:
2016-04-05 12:03:08 +00:00
DVector2 delta; // precalculated v2 - v1 for side checking
public:
uint32_t flags;
uint32_t activation; // activation type
2016-03-01 15:47:10 +00:00
int special;
int args[5]; // <--- hexen-style arguments (expanded to ZDoom's full width)
double alpha; // <--- translucency (0=invisibile, FRACUNIT=opaque)
2016-03-01 15:47:10 +00:00
side_t *sidedef[2];
2016-03-30 23:22:49 +00:00
double bbox[4]; // bounding box, for the extent of the LineDef.
2016-03-01 15:47:10 +00:00
sector_t *frontsector, *backsector;
int validcount; // if == validcount, already checked
int locknumber; // [Dusk] lock number for special
unsigned portalindex;
unsigned portaltransferred;
2016-03-01 15:47:10 +00:00
DVector2 Delta() const
{
2016-04-05 12:03:08 +00:00
return delta;
}
void setDelta(double x, double y)
{
2016-04-05 12:03:08 +00:00
delta = { x, y };
}
void setAlpha(double a)
{
alpha = a;
}
FSectorPortal *GetTransferredPortal()
{
return portaltransferred >= sectorPortals.Size() ? (FSectorPortal*)NULL : &sectorPortals[portaltransferred];
}
2016-03-01 15:47:10 +00:00
FLinePortal *getPortal() const
{
return portalindex >= linePortals.Size() ? (FLinePortal*)NULL : &linePortals[portalindex];
}
// returns true if the portal is crossable by actors
bool isLinePortal() const
{
return portalindex >= linePortals.Size() ? false : !!(linePortals[portalindex].mFlags & PORTF_PASSABLE);
}
// returns true if the portal needs to be handled by the renderer
bool isVisualPortal() const
{
return portalindex >= linePortals.Size() ? false : !!(linePortals[portalindex].mFlags & PORTF_VISIBLE);
}
line_t *getPortalDestination() const
{
return portalindex >= linePortals.Size() ? (line_t*)NULL : linePortals[portalindex].mDestination;
}
int getPortalAlignment() const
{
return portalindex >= linePortals.Size() ? 0 : linePortals[portalindex].mAlign;
}
};
// phares 3/14/98
//
// Sector list node showing all sectors an object appears in.
//
// There are two threads that flow through these nodes. The first thread
// starts at touching_thinglist in a sector_t and flows through the m_snext
// links to find all mobjs that are entirely or partially in the sector.
// The second thread starts at touching_sectorlist in a AActor and flows
// through the m_tnext links to find all sectors a thing touches. This is
// useful when applying friction or push effects to sectors. These effects
// can be done as thinkers that act upon all objects touching their sectors.
// As an mobj moves through the world, these nodes are created and
// destroyed, with the links changed appropriately.
//
// For the links, NULL means top or end of list.
struct msecnode_t
{
sector_t *m_sector; // a sector containing this object
AActor *m_thing; // this object
struct msecnode_t *m_tprev; // prev msecnode_t for this thing
struct msecnode_t *m_tnext; // next msecnode_t for this thing
struct msecnode_t *m_sprev; // prev msecnode_t for this sector
struct msecnode_t *m_snext; // next msecnode_t for this sector
bool visited; // killough 4/4/98, 4/7/98: used in search algorithms
};
// use the same memory layout as msecnode_t so both can be used from the same freelist.
struct portnode_t
{
FLinePortal *m_portal; // a portal containing this object
AActor *m_thing; // this object
struct portnode_t *m_tprev; // prev msecnode_t for this thing
struct portnode_t *m_tnext; // next msecnode_t for this thing
struct portnode_t *m_sprev; // prev msecnode_t for this portal
struct portnode_t *m_snext; // next msecnode_t for this portal
bool visited;
};
2016-03-01 15:47:10 +00:00
struct FPolyNode;
struct FMiniBSP;
//
// The LineSeg.
//
struct seg_t
{
vertex_t* v1;
vertex_t* v2;
side_t* sidedef;
line_t* linedef;
// Sector references. Could be retrieved from linedef, too.
sector_t* frontsector;
sector_t* backsector; // NULL for one-sided lines
seg_t* PartnerSeg;
subsector_t* Subsector;
float sidefrac; // relative position of seg's ending vertex on owning sidedef
2016-03-01 15:47:10 +00:00
};
struct glsegextra_t
{
DWORD PartnerSeg;
subsector_t *Subsector;
};
extern seg_t *segs;
2016-03-01 15:47:10 +00:00
//
// A SubSector.
// References a Sector.
// Basically, this is a list of LineSegs indicating the visible walls that
// define (all or some) sides of a convex BSP leaf.
//
enum
{
SSECF_DEGENERATE = 1,
SSECF_DRAWN = 2,
SSECF_POLYORG = 4,
};
struct FPortalCoverage
{
DWORD * subsectors;
int sscount;
};
2016-03-01 15:47:10 +00:00
struct subsector_t
{
sector_t *sector;
FPolyNode *polys;
FMiniBSP *BSP;
seg_t *firstline;
sector_t *render_sector;
DWORD numlines;
int flags;
void BuildPolyBSP();
// subsector related GL data
FLightNode * lighthead; // Light nodes (blended and additive)
int validcount;
short mapsection;
char hacked; // 1: is part of a render hack
// 2: has one-sided walls
FPortalCoverage portalcoverage[2];
2016-03-01 15:47:10 +00:00
};
//
// BSP node.
//
struct node_t
{
// Partition line.
fixed_t x;
fixed_t y;
fixed_t dx;
fixed_t dy;
2016-05-01 03:37:02 +00:00
union
{
float bbox[2][4]; // Bounding box for each child.
fixed_t nb_bbox[2][4]; // Used by nodebuilder.
};
2016-03-01 15:47:10 +00:00
float len;
union
{
void *children[2]; // If bit 0 is set, it's a subsector.
int intchildren[2]; // Used by nodebuilder.
};
};
// An entire BSP tree.
struct FMiniBSP
{
bool bDirty;
TArray<node_t> Nodes;
TArray<seg_t> Segs;
TArray<subsector_t> Subsectors;
TArray<vertex_t> Verts;
};
//
// OTHER TYPES
//
typedef BYTE lighttable_t; // This could be wider for >8 bit display.
2016-09-14 08:03:39 +00:00
struct FSWColormap;
2016-03-01 15:47:10 +00:00
// This encapsulates the fields of vissprite_t that can be altered by AlterWeaponSprite
struct visstyle_t
{
int ColormapNum; // Which colormap is rendered
2016-09-14 08:03:39 +00:00
FSWColormap *BaseColormap; // Base colormap used together with ColormapNum
2016-09-14 10:28:39 +00:00
lighttable_t *colormap; // [SP] Restored from GZDoom - will this work?
float Alpha;
2016-03-01 15:47:10 +00:00
FRenderStyle RenderStyle;
};
//----------------------------------------------------------------------------------
//
// The playsim can use different nodes than the renderer so this is
// not the same as R_PointInSubsector
//
//----------------------------------------------------------------------------------
subsector_t *P_PointInSubsector(double x, double y);
2016-03-01 15:47:10 +00:00
inline sector_t *P_PointInSector(const DVector2 &pos)
{
return P_PointInSubsector(pos.X, pos.Y)->sector;
}
2016-03-25 20:54:59 +00:00
inline sector_t *P_PointInSector(double X, double Y)
{
return P_PointInSubsector(X, Y)->sector;
2016-03-25 20:54:59 +00:00
}
inline DVector3 AActor::PosRelative(int portalgroup) const
{
return Pos() + Displacements.getOffset(Sector->PortalGroup, portalgroup);
}
inline DVector3 AActor::PosRelative(const AActor *other) const
{
return Pos() + Displacements.getOffset(Sector->PortalGroup, other->Sector->PortalGroup);
}
inline DVector3 AActor::PosRelative(sector_t *sec) const
{
return Pos() + Displacements.getOffset(Sector->PortalGroup, sec->PortalGroup);
}
inline DVector3 AActor::PosRelative(line_t *line) const
{
return Pos() + Displacements.getOffset(Sector->PortalGroup, line->frontsector->PortalGroup);
}
inline DVector3 PosRelative(const DVector3 &pos, line_t *line, sector_t *refsec = NULL)
2016-03-01 15:47:10 +00:00
{
return pos + Displacements.getOffset(refsec->PortalGroup, line->frontsector->PortalGroup);
}
2016-03-01 15:47:10 +00:00
inline void AActor::ClearInterpolation()
{
Prev = Pos();
PrevAngles = Angles;
2016-03-01 15:47:10 +00:00
if (Sector) PrevPortalGroup = Sector->PortalGroup;
else PrevPortalGroup = 0;
}
inline bool FBoundingBox::inRange(const line_t *ld) const
{
2016-03-31 08:38:54 +00:00
return Left() < ld->bbox[BOXRIGHT] &&
Right() > ld->bbox[BOXLEFT] &&
Top() > ld->bbox[BOXBOTTOM] &&
Bottom() < ld->bbox[BOXTOP];
}
2016-03-01 15:47:10 +00:00
2016-03-01 15:47:10 +00:00
#endif