mirror of
https://github.com/ZDoom/gzdoom.git
synced 2025-02-21 11:31:41 +00:00
added wall texture skewing.
This uses the same UDMF properties as Eternity recently introduced for the same feature.
This commit is contained in:
parent
9cd57faec1
commit
f92f6b8de4
7 changed files with 151 additions and 26 deletions
|
@ -1194,6 +1194,19 @@ struct side_t
|
|||
walltop = 0,
|
||||
wallbottom = 1,
|
||||
};
|
||||
enum ESkew
|
||||
{
|
||||
skew_none = 0,
|
||||
skew_front = 1,
|
||||
skew_back = 2,
|
||||
// for mid textures there's 4 options
|
||||
skew_front_floor = 1,
|
||||
skew_front_ceiling = 2,
|
||||
skew_back_floor = 3,
|
||||
skew_back_ceiling = 4
|
||||
|
||||
};
|
||||
|
||||
struct part
|
||||
{
|
||||
enum EPartFlags
|
||||
|
@ -1209,7 +1222,8 @@ struct side_t
|
|||
double xScale;
|
||||
double yScale;
|
||||
TObjPtr<DInterpolation*> interpolation;
|
||||
int flags;
|
||||
int16_t flags;
|
||||
int8_t skew;
|
||||
FTextureID texture;
|
||||
TextureManipulation TextureFx;
|
||||
PalEntry SpecialColors[2];
|
||||
|
|
|
@ -104,6 +104,24 @@ static char HexenSectorSpecialOk[256]={
|
|||
1,1,1,1,1,
|
||||
};
|
||||
|
||||
static const char* udmfsolidskewtypes[] =
|
||||
{
|
||||
"none",
|
||||
"front",
|
||||
"back",
|
||||
nullptr
|
||||
};
|
||||
|
||||
static const char* udmfmaskedskewtypes[] =
|
||||
{
|
||||
"none",
|
||||
"front_floor",
|
||||
"front_ceiling",
|
||||
"back_floor",
|
||||
"back_ceiling",
|
||||
nullptr
|
||||
};
|
||||
|
||||
static inline bool P_IsThingSpecial(int specnum)
|
||||
{
|
||||
return (specnum >= Thing_Projectile && specnum <= Thing_SpawnNoFog) ||
|
||||
|
@ -282,6 +300,20 @@ const char *UDMFParserBase::CheckString(FName key)
|
|||
return parsedString.GetChars();
|
||||
}
|
||||
|
||||
int UDMFParserBase::MatchString(FName key, const char* const* strings, int defval)
|
||||
{
|
||||
const char* string = CheckString(key);
|
||||
for (int i = 0; *strings != nullptr; i++, strings++)
|
||||
{
|
||||
if (!stricmp(string, *strings))
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
sc.ScriptMessage("Unknown value %s for key '%s'", string, key.GetChars());
|
||||
return defval;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Storage of UDMF user properties
|
||||
|
@ -1484,6 +1516,22 @@ public:
|
|||
CHECK_N(Zd | Zdt)
|
||||
break;
|
||||
|
||||
case NAME_skew_top_type:
|
||||
CHECK_N(Zd | Zdt)
|
||||
sd->textures[side_t::top].skew = MatchString(key, udmfsolidskewtypes, 0);
|
||||
break;
|
||||
|
||||
case NAME_skew_middle_type:
|
||||
CHECK_N(Zd | Zdt)
|
||||
sd->textures[side_t::mid].skew = MatchString(key, udmfmaskedskewtypes, 0);
|
||||
break;
|
||||
|
||||
case NAME_skew_bottom_type:
|
||||
CHECK_N(Zd | Zdt)
|
||||
sd->textures[side_t::bottom].skew = MatchString(key, udmfsolidskewtypes, 0);
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
if (strnicmp("user_", key.GetChars(), 5))
|
||||
DPrintf(DMSG_WARNING, "Unknown UDMF sidedef key %s\n", key.GetChars());
|
||||
|
@ -2200,6 +2248,17 @@ public:
|
|||
sides[side].sector = &Level->sectors[intptr_t(sides[side].sector)];
|
||||
lines[line].sidedef[sd] = &sides[side];
|
||||
|
||||
if (sd == 1)
|
||||
{
|
||||
// fix flags for backside. The definition is linedef relative, not sidedef relative.
|
||||
static const uint8_t swaps[] = { 0, side_t::skew_back, side_t::skew_front };
|
||||
static const uint8_t swapsm[] = {0, side_t::skew_back_floor, side_t::skew_back_ceiling, side_t::skew_front_floor, side_t::skew_front_ceiling};
|
||||
|
||||
sides[side].textures[side_t::top].skew = swaps[sides[side].textures[side_t::top].skew];
|
||||
sides[side].textures[side_t::bottom].skew = swaps[sides[side].textures[side_t::bottom].skew];
|
||||
sides[side].textures[side_t::mid].skew = swapsm[sides[side].textures[side_t::mid].skew];
|
||||
}
|
||||
|
||||
loader->ProcessSideTextures(!isExtended, &sides[side], sides[side].sector, &ParsedSideTextures[mapside],
|
||||
lines[line].special, lines[line].args[0], &tempalpha[sd], missingTex);
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ protected:
|
|||
DAngle CheckAngle(FName key);
|
||||
bool CheckBool(FName key);
|
||||
const char *CheckString(FName key);
|
||||
int MatchString(FName key, const char* const* strings, int defval);
|
||||
|
||||
template<typename T>
|
||||
bool Flag(T &value, int mask, FName key)
|
||||
|
|
|
@ -858,4 +858,8 @@ xx(lm_sampledist_ceiling)
|
|||
xx(lm_suncolor)
|
||||
xx(lm_sampledistance)
|
||||
|
||||
xx(skew_bottom_type)
|
||||
xx(skew_middle_type)
|
||||
xx(skew_top_type)
|
||||
|
||||
xx(Corona)
|
||||
|
|
|
@ -140,6 +140,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, side_t::part &part, si
|
|||
("texture", part.texture, def->texture)
|
||||
("interpolation", part.interpolation)
|
||||
("flags", part.flags, def->flags)
|
||||
("skew", part.skew, def->skew)
|
||||
("color1", part.SpecialColors[0], def->SpecialColors[0])
|
||||
("color2", part.SpecialColors[1], def->SpecialColors[1])
|
||||
("addcolor", part.AdditiveColor, def->AdditiveColor)
|
||||
|
|
|
@ -237,19 +237,19 @@ public:
|
|||
bool DoHorizon(HWWallDispatcher* di, seg_t* seg, sector_t* fs, vertex_t* v1, vertex_t* v2);
|
||||
|
||||
bool SetWallCoordinates(seg_t* seg, FTexCoordInfo* tci, float ceilingrefheight,
|
||||
float topleft, float topright, float bottomleft, float bottomright, float t_ofs);
|
||||
float topleft, float topright, float bottomleft, float bottomright, float t_ofs, float skew);
|
||||
|
||||
void DoTexture(HWWallDispatcher* di, int type, seg_t* seg, int peg,
|
||||
float ceilingrefheight, float floorrefheight,
|
||||
float CeilingHeightstart, float CeilingHeightend,
|
||||
float FloorHeightstart, float FloorHeightend,
|
||||
float v_offset);
|
||||
float v_offset, float skew);
|
||||
|
||||
void DoMidTexture(HWWallDispatcher* di, seg_t* seg, bool drawfogboundary,
|
||||
sector_t* front, sector_t* back,
|
||||
sector_t* realfront, sector_t* realback,
|
||||
float fch1, float fch2, float ffh1, float ffh2,
|
||||
float bch1, float bch2, float bfh1, float bfh2, float zalign);
|
||||
float bch1, float bch2, float bfh1, float bfh2, float zalign, float skew);
|
||||
|
||||
void GetPlanePos(F3DFloor::planeref* planeref, float& left, float& right);
|
||||
|
||||
|
|
|
@ -1016,7 +1016,7 @@ static float ZeroLightmapUVs[8] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.
|
|||
//
|
||||
//==========================================================================
|
||||
bool HWWall::SetWallCoordinates(seg_t * seg, FTexCoordInfo *tci, float texturetop,
|
||||
float topleft, float topright, float bottomleft, float bottomright, float t_ofs)
|
||||
float topleft, float topright, float bottomleft, float bottomright, float t_ofs, float skew)
|
||||
{
|
||||
//
|
||||
//
|
||||
|
@ -1109,8 +1109,8 @@ bool HWWall::SetWallCoordinates(seg_t * seg, FTexCoordInfo *tci, float textureto
|
|||
|
||||
if (tci)
|
||||
{
|
||||
tcs[UPRGT].v = tci->FloatToTexV(-ztop[1] + texturetop);
|
||||
tcs[LORGT].v = tci->FloatToTexV(-zbottom[1] + texturetop);
|
||||
tcs[UPRGT].v = tci->FloatToTexV(-ztop[1] + texturetop + skew);
|
||||
tcs[LORGT].v = tci->FloatToTexV(-zbottom[1] + texturetop + skew);
|
||||
}
|
||||
|
||||
lightuv[UPRGT].v = srclightuv[UPRGT].v;
|
||||
|
@ -1132,7 +1132,7 @@ bool HWWall::SetWallCoordinates(seg_t * seg, FTexCoordInfo *tci, float textureto
|
|||
zbottom[1] = ztop[1] = inter_y;
|
||||
if (tci)
|
||||
{
|
||||
tcs[LORGT].v = tcs[UPRGT].v = tci->FloatToTexV(-ztop[1] + texturetop);
|
||||
tcs[LORGT].v = tcs[UPRGT].v = tci->FloatToTexV(-ztop[1] + texturetop + skew);
|
||||
}
|
||||
|
||||
lightuv[UPRGT].v = srclightuv[UPRGT].v + inter_x * (srclightuv[UPRGT].v - srclightuv[UPLFT].v);
|
||||
|
@ -1258,7 +1258,7 @@ void HWWall::DoTexture(HWWallDispatcher *di, int _type,seg_t * seg, int peg,
|
|||
float ceilingrefheight,float floorrefheight,
|
||||
float topleft,float topright,
|
||||
float bottomleft,float bottomright,
|
||||
float v_offset)
|
||||
float v_offset, float skew)
|
||||
{
|
||||
if (topleft<=bottomleft && topright<=bottomright) return;
|
||||
|
||||
|
@ -1300,7 +1300,7 @@ void HWWall::DoTexture(HWWallDispatcher *di, int _type,seg_t * seg, int peg,
|
|||
if (peg) floatceilingref += tci.mRenderHeight - flh - v_offset;
|
||||
|
||||
if (!SetWallCoordinates(seg, &tci, floatceilingref, topleft, topright, bottomleft, bottomright,
|
||||
seg->sidedef->GetTextureXOffset(texpos))) return;
|
||||
seg->sidedef->GetTextureXOffset(texpos), skew)) return;
|
||||
|
||||
if (seg->linedef->special == Line_Mirror && _type == RENDERWALL_M1S && gl_mirrors && !(di->Level->ib_compatflags & BCOMPATF_NOMIRRORS))
|
||||
{
|
||||
|
@ -1332,7 +1332,7 @@ void HWWall::DoMidTexture(HWWallDispatcher *di, seg_t * seg, bool drawfogboundar
|
|||
sector_t * front, sector_t * back,
|
||||
sector_t * realfront, sector_t * realback,
|
||||
float fch1, float fch2, float ffh1, float ffh2,
|
||||
float bch1, float bch2, float bfh1, float bfh2, float zalign)
|
||||
float bch1, float bch2, float bfh1, float bfh2, float zalign, float skew)
|
||||
|
||||
{
|
||||
FTexCoordInfo tci;
|
||||
|
@ -1449,10 +1449,10 @@ void HWWall::DoMidTexture(HWWallDispatcher *di, seg_t * seg, bool drawfogboundar
|
|||
// if we don't need a fog sheet let's clip away some unnecessary parts of the polygon
|
||||
//
|
||||
//
|
||||
if (!drawfogboundary && !wrap)
|
||||
if (!drawfogboundary && !wrap && skew == 0)
|
||||
{
|
||||
if (texturetop<topleft && texturetop<topright) topleft=topright=texturetop;
|
||||
if (texturebottom>bottomleft && texturebottom>bottomright) bottomleft=bottomright=texturebottom;
|
||||
if (texturetop < topleft && texturetop < topright) topleft = topright = texturetop;
|
||||
if (texturebottom > bottomleft && texturebottom > bottomright) bottomleft = bottomright = texturebottom;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1465,8 +1465,10 @@ void HWWall::DoMidTexture(HWWallDispatcher *di, seg_t * seg, bool drawfogboundar
|
|||
// unwanted side effects.
|
||||
//
|
||||
//
|
||||
topleft=topright=texturetop;
|
||||
bottomleft=bottomright=texturebottom;
|
||||
topleft = texturetop;
|
||||
topright = texturetop + skew;
|
||||
bottomleft = texturebottom;
|
||||
bottomright = texturebottom + skew;
|
||||
}
|
||||
|
||||
// nothing visible - skip the rest
|
||||
|
@ -1529,7 +1531,7 @@ void HWWall::DoMidTexture(HWWallDispatcher *di, seg_t * seg, bool drawfogboundar
|
|||
// mid textures on portal lines need the same offsetting as mid textures on sky lines
|
||||
flags |= HWF_SKYHACK;
|
||||
}
|
||||
SetWallCoordinates(seg, &tci, texturetop, topleft, topright, bottomleft, bottomright, t_ofs);
|
||||
SetWallCoordinates(seg, &tci, texturetop, topleft, topright, bottomleft, bottomright, t_ofs, skew);
|
||||
|
||||
//
|
||||
//
|
||||
|
@ -1588,7 +1590,7 @@ void HWWall::DoMidTexture(HWWallDispatcher *di, seg_t * seg, bool drawfogboundar
|
|||
FloatRect *splitrect;
|
||||
int v = texture->GetAreas(&splitrect);
|
||||
if (seg->frontsector == seg->backsector) flags |= HWF_NOSPLIT; // we don't need to do vertex splits if a line has both sides in the same sector
|
||||
if (v>0 && !drawfogboundary && !(seg->linedef->flags&ML_WRAP_MIDTEX) && !(flags & HWF_NOSLICE))
|
||||
if (v>0 && !drawfogboundary && !(seg->linedef->flags&ML_WRAP_MIDTEX) && !(flags & HWF_NOSLICE) && skew == 0)
|
||||
{
|
||||
// split the poly!
|
||||
int i,t=0;
|
||||
|
@ -2042,6 +2044,10 @@ inline int CalcRelLight(int lightlevel, int orglightlevel, int rel)
|
|||
}
|
||||
}
|
||||
|
||||
CVAR(Int, topskew, 0, 0)
|
||||
CVAR(Int, midskew, 0, 0)
|
||||
CVAR(Int, bottomskew, 0, 0)
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
|
@ -2198,9 +2204,14 @@ void HWWall::Process(HWWallDispatcher *di, seg_t *seg, sector_t * frontsector, s
|
|||
texture = TexMan.GetGameTexture(seg->sidedef->GetTexture(side_t::mid), true);
|
||||
if (texture && texture->isValid())
|
||||
{
|
||||
int skewflag = seg->sidedef->textures[side_t::mid].skew;
|
||||
if (skewflag == 0) skewflag = midskew;
|
||||
float skew =
|
||||
skewflag == side_t::skew_front_ceiling ? fch2 - fch1 :
|
||||
skewflag == side_t::skew_front_floor ? ffh2 - ffh1 : 0.;
|
||||
DoTexture(di, RENDERWALL_M1S, seg, (seg->linedef->flags & ML_DONTPEGBOTTOM) > 0,
|
||||
crefz, frefz, // must come from the original!
|
||||
fch1, fch2, ffh1, ffh2, 0);
|
||||
fch1, fch2, ffh1, ffh2, 0, skew);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2268,9 +2279,15 @@ void HWWall::Process(HWWallDispatcher *di, seg_t *seg, sector_t * frontsector, s
|
|||
texture = TexMan.GetGameTexture(seg->sidedef->GetTexture(side_t::top), true);
|
||||
if (texture && texture->isValid())
|
||||
{
|
||||
int skewflag = seg->sidedef->textures[side_t::top].skew;
|
||||
if (skewflag == 0) skewflag = topskew;
|
||||
float skew =
|
||||
skewflag == side_t::skew_front ? fch2 - fch1 :
|
||||
skewflag == side_t::skew_back ? bch2 - bch1 : 0.;
|
||||
|
||||
DoTexture(di, RENDERWALL_TOP, seg, (seg->linedef->flags & (ML_DONTPEGTOP)) == 0,
|
||||
crefz, realback->GetPlaneTexZ(sector_t::ceiling),
|
||||
fch1, fch2, bch1a, bch2a, 0);
|
||||
fch1, fch2, bch1a, bch2a, 0, skew);
|
||||
}
|
||||
else if (!(seg->sidedef->Flags & WALLF_POLYOBJ))
|
||||
{
|
||||
|
@ -2283,7 +2300,7 @@ void HWWall::Process(HWWallDispatcher *di, seg_t *seg, sector_t * frontsector, s
|
|||
{
|
||||
DoTexture(di, RENDERWALL_TOP, seg, (seg->linedef->flags & (ML_DONTPEGTOP)) == 0,
|
||||
crefz, realback->GetPlaneTexZ(sector_t::ceiling),
|
||||
fch1, fch2, bch1a, bch2a, 0);
|
||||
fch1, fch2, bch1a, bch2a, 0, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -2318,6 +2335,28 @@ void HWWall::Process(HWWallDispatcher *di, seg_t *seg, sector_t * frontsector, s
|
|||
lightlevel = hw_ClampLight(seg->sidedef->GetLightLevel(foggy, orglightlevel, side_t::mid, false, &rel));
|
||||
rellight = CalcRelLight(lightlevel, orglightlevel, rel);
|
||||
|
||||
float skew;
|
||||
int skewflag = seg->sidedef->textures[side_t::mid].skew;
|
||||
if (skewflag == 0) skewflag = midskew;
|
||||
switch (skewflag)
|
||||
{
|
||||
default:
|
||||
skew = 0;
|
||||
break;
|
||||
case side_t::skew_front_ceiling:
|
||||
skew = fch2 - fch1;
|
||||
break;
|
||||
case side_t::skew_back_ceiling:
|
||||
skew = bch2 - bch1;
|
||||
break;
|
||||
case side_t::skew_front_floor:
|
||||
skew = bfh2 - bfh1;
|
||||
break;
|
||||
case side_t::skew_back_floor:
|
||||
skew = ffh2 - ffh1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (isportal)
|
||||
{
|
||||
lineportal = seg->linedef->getPortal()->mGroup;
|
||||
|
@ -2330,7 +2369,7 @@ void HWWall::Process(HWWallDispatcher *di, seg_t *seg, sector_t * frontsector, s
|
|||
if (texture && seg->backsector != nullptr)
|
||||
{
|
||||
DoMidTexture(di, seg, drawfogboundary, frontsector, backsector, realfront, realback,
|
||||
fch1, fch2, ffh1, ffh2, bch1, bch2, bfh1, bfh2, zalign);
|
||||
fch1, fch2, ffh1, ffh2, bch1, bch2, bfh1, bfh2, zalign, skew);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -2339,7 +2378,7 @@ void HWWall::Process(HWWallDispatcher *di, seg_t *seg, sector_t * frontsector, s
|
|||
if (texture || drawfogboundary)
|
||||
{
|
||||
DoMidTexture(di, seg, drawfogboundary, frontsector, backsector, realfront, realback,
|
||||
fch1, fch2, ffh1, ffh2, bch1, bch2, bfh1, bfh2, zalign);
|
||||
fch1, fch2, ffh1, ffh2, bch1, bch2, bfh1, bfh2, zalign, skew);
|
||||
}
|
||||
|
||||
if (backsector->e->XFloor.ffloors.Size() || frontsector->e->XFloor.ffloors.Size())
|
||||
|
@ -2352,6 +2391,7 @@ void HWWall::Process(HWWallDispatcher *di, seg_t *seg, sector_t * frontsector, s
|
|||
|
||||
/* bottom texture */
|
||||
// the back sector's ceiling obstructs part of this wall (specially important for sky sectors)
|
||||
float bfh1a = bch1, bfh2a = bch2;
|
||||
if (fch1 < bfh1 && fch2 < bfh2 && (seg->linedef->flags & ML_DRAWFULLHEIGHT) == 0)
|
||||
{
|
||||
bfh1 = fch1;
|
||||
|
@ -2365,12 +2405,18 @@ void HWWall::Process(HWWallDispatcher *di, seg_t *seg, sector_t * frontsector, s
|
|||
texture = TexMan.GetGameTexture(seg->sidedef->GetTexture(side_t::bottom), true);
|
||||
if (texture && texture->isValid())
|
||||
{
|
||||
int skewflag = seg->sidedef->textures[side_t::bottom].skew;
|
||||
if (skewflag == 0) skewflag = bottomskew;
|
||||
float skew =
|
||||
skewflag == side_t::skew_back ? bfh2a - bfh1a :
|
||||
skewflag == side_t::skew_front ? ffh2 - ffh1 : 0.;
|
||||
|
||||
DoTexture(di, RENDERWALL_BOTTOM, seg, (seg->linedef->flags & ML_DONTPEGBOTTOM) > 0,
|
||||
realback->GetPlaneTexZ(sector_t::floor), frefz,
|
||||
bfh1, bfh2, ffh1, ffh2,
|
||||
frontsector->GetTexture(sector_t::ceiling) == skyflatnum && backsector->GetTexture(sector_t::ceiling) == skyflatnum ?
|
||||
frefz - realback->GetPlaneTexZ(sector_t::ceiling) :
|
||||
frefz - crefz);
|
||||
frefz - crefz, skew);
|
||||
}
|
||||
else if (!(seg->sidedef->Flags & WALLF_POLYOBJ))
|
||||
{
|
||||
|
@ -2386,7 +2432,7 @@ void HWWall::Process(HWWallDispatcher *di, seg_t *seg, sector_t * frontsector, s
|
|||
{
|
||||
DoTexture(di, RENDERWALL_BOTTOM, seg, (seg->linedef->flags & ML_DONTPEGBOTTOM) > 0,
|
||||
realback->GetPlaneTexZ(sector_t::floor), frefz,
|
||||
bfh1, bfh2, ffh1, ffh2, frefz - crefz);
|
||||
bfh1, bfh2, ffh1, ffh2, frefz - crefz, 0);
|
||||
}
|
||||
}
|
||||
else if (backsector->GetTexture(sector_t::floor) != skyflatnum)
|
||||
|
@ -2458,7 +2504,7 @@ void HWWall::ProcessLowerMiniseg(HWWallDispatcher *di, seg_t *seg, sector_t * fr
|
|||
FTexCoordInfo tci;
|
||||
type = RENDERWALL_BOTTOM;
|
||||
tci.GetFromTexture(texture, 1, 1, false);
|
||||
SetWallCoordinates(seg, &tci, bfh, bfh, bfh, ffh, ffh, 0);
|
||||
SetWallCoordinates(seg, &tci, bfh, bfh, bfh, ffh, ffh, 0, 0);
|
||||
PutWall(di, false);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue