Merge branch 'texture-skewing' into 'master'

Implement proper texture skewing in Visual Mode

See merge request STJr/UltimateZoneBuilder!5
This commit is contained in:
sphere 2023-05-26 12:51:41 +00:00
commit 10e2e3f4cb
7 changed files with 435 additions and 136 deletions

View file

@ -625,6 +625,8 @@ speciallinedefs
impassableflag = 1;
upperunpeggedflag = 8;
lowerunpeggedflag = 16;
slopeskewflag = 32;
nomidtextureskewflag = 128;
repeatmidtextureflag = 1024;
pegmidtextureflag = 256;
}
@ -639,6 +641,8 @@ speciallinedefs_udmf
lowerunpeggedflag = "dontpegbottom";
repeatmidtextureflag = "wrapmidtex";
pegmidtextureflag = "midpeg";
slopeskewflag = "skewtd";
nomidtextureskewflag = "noskew";
}
scriptlumpnames

View file

@ -77,6 +77,8 @@ namespace CodeImp.DoomBuilder.Config
private readonly string upperunpeggedflag;
private readonly string lowerunpeggedflag;
private readonly string pegmidtextureflag;
private readonly string slopeskewflag;
private readonly string nomidtextureskewflag;
private readonly bool mixtexturesflats;
private readonly bool generalizedactions;
private readonly bool generalizedeffects;
@ -245,6 +247,8 @@ namespace CodeImp.DoomBuilder.Config
public string UpperUnpeggedFlag { get { return upperunpeggedflag; } }
public string LowerUnpeggedFlag { get { return lowerunpeggedflag; } }
public string PegMidtextureFlag { get { return pegmidtextureflag; } }
public string SlopeSkewFlag { get { return slopeskewflag; } }
public string NoMidtextureSkewFlag { get { return nomidtextureskewflag; } }
public bool MixTexturesFlats { get { return mixtexturesflats; } }
public bool GeneralizedActions { get { return generalizedactions; } }
public bool GeneralizedEffects { get { return generalizedeffects; } }
@ -531,6 +535,10 @@ namespace CodeImp.DoomBuilder.Config
pegmidtextureflag = ((int)obj == 0) ? lowerunpeggedflag : ((int)obj).ToString(CultureInfo.InvariantCulture);
else
pegmidtextureflag = obj.ToString();
obj = cfg.ReadSettingObject("slopeskewflag", 0);
if (obj is int) slopeskewflag = ((int)obj).ToString(CultureInfo.InvariantCulture); else slopeskewflag = obj.ToString();
obj = cfg.ReadSettingObject("nomidtextureskewflag", 0);
if (obj is int) nomidtextureskewflag = ((int)obj).ToString(CultureInfo.InvariantCulture); else nomidtextureskewflag = obj.ToString();
// Get texture and flat sources
textureranges = cfg.ReadSetting("textures", new Hashtable());

View file

@ -156,40 +156,89 @@ namespace CodeImp.DoomBuilder.BuilderModes
// the values are stored in a TexturePlane)
// NOTE: I use a small bias for the floor height, because if the difference in
// height is 0 then the TexturePlane doesn't work!
TexturePlane tp = new TexturePlane();
Vector3D vlt, vlb, vrt, vrb;
Vector2D tlt, tlb, trt, trb;
double floorbias = (Sidedef.Other.Sector.FloorHeight == Sidedef.Sector.FloorHeight) ? 1.0 : 0.0;
if(Sidedef.Line.IsFlagSet(General.Map.Config.LowerUnpeggedFlag))
double planefloorbias = Math.Abs(osd.Floor.plane.GetZ(vr) - sd.Floor.plane.GetZ(vr)) < 0.5 ? 1.0 : 0.0;
double texturevpeg = 0;
bool lowerunpegged = Sidedef.Line.IsFlagSet(General.Map.Config.LowerUnpeggedFlag);
bool slopeskew = Sidedef.Line.IsFlagSet(General.Map.Config.SlopeSkewFlag);
if (lowerunpegged)
{
if(Sidedef.Sector.HasSkyCeiling && Sidedef.Other.Sector.HasSkyCeiling)
if (slopeskew)
{
// mxd. Replicate Doom texture offset glitch when front and back sector's ceilings are sky
tp.tlt.y = (double)Sidedef.Other.Sector.CeilHeight - Sidedef.Other.Sector.FloorHeight;
}
texturevpeg = sd.Ceiling.plane.GetZ(vl) - osd.Floor.plane.GetZ(vl);
}
//if(Sidedef.Sector.HasSkyCeiling && Sidedef.Other.Sector.HasSkyCeiling)
//{
// // mxd. Replicate Doom texture offset glitch when front and back sector's ceilings are sky
// texturevpeg = (double)Sidedef.Other.Sector.CeilHeight - Sidedef.Other.Sector.FloorHeight;
//}
else
{
// When lower unpegged is set, the lower texture is bound to the bottom
tp.tlt.y = (double) Sidedef.Sector.CeilHeight - Sidedef.Other.Sector.FloorHeight;
texturevpeg = (double) Sidedef.Sector.CeilHeight - Sidedef.Other.Sector.FloorHeight;
}
}
tp.trb.x = tp.tlt.x + Math.Round(Sidedef.Line.Length); //mxd. (G)ZDoom snaps texture coordinates to integral linedef length
tp.trb.y = tp.tlt.y + (Sidedef.Other.Sector.FloorHeight - (Sidedef.Sector.FloorHeight + floorbias));
tlt.x = tlb.x = 0;
trt.x = trb.x = Math.Round(Sidedef.Line.Length); //mxd. (G)ZDoom snaps texture coordinates to integral linedef length
tlt.y = trt.y = texturevpeg;
tlb.y = trb.y = texturevpeg + (Sidedef.Other.Sector.FloorHeight - (Sidedef.Sector.FloorHeight + floorbias));
if (!slopeskew)
{
// Unskewed
tlb.y -= sd.Floor.plane.GetZ(vl) - Sidedef.Sector.FloorHeight;
trb.y -= sd.Floor.plane.GetZ(vr) - Sidedef.Sector.FloorHeight;
tlt.y -= osd.Floor.plane.GetZ(vl) - Sidedef.Other.Sector.FloorHeight;
trt.y -= osd.Floor.plane.GetZ(vr) - Sidedef.Other.Sector.FloorHeight;
}
else if (lowerunpegged)
{
// Skewed by bottom
tlb.y = texturevpeg + osd.Floor.plane.GetZ(vl) - sd.Floor.plane.GetZ(vl);
trb.y = tlb.y;
tlt.y = tlb.y - (osd.Floor.plane.GetZ(vl) - sd.Floor.plane.GetZ(vl));
trt.y = trb.y - (osd.Floor.plane.GetZ(vr) - sd.Floor.plane.GetZ(vr));
}
else
{
// Skewed by top
tlb.y = texturevpeg + osd.Floor.plane.GetZ(vl) - sd.Floor.plane.GetZ(vl);
trb.y = texturevpeg + osd.Floor.plane.GetZ(vr) - sd.Floor.plane.GetZ(vr);
}
if (Math.Abs(trb.y - trt.y) < 0.5f) trb.y = trt.y - 1.0f;
// Apply texture offset
tp.tlt += tof;
tp.trb += tof;
tlt += tof;
tlb += tof;
trb += tof;
trt += tof;
// Transform pixel coordinates to texture coordinates
tp.tlt /= tsz;
tp.trb /= tsz;
// Left top and right bottom of the geometry that
tp.vlt = new Vector3D(vl.x, vl.y, Sidedef.Other.Sector.FloorHeight);
tp.vrb = new Vector3D(vr.x, vr.y, Sidedef.Sector.FloorHeight + floorbias);
// Make the right-top coordinates
tp.trt = new Vector2D(tp.trb.x, tp.tlt.y);
tp.vrt = new Vector3D(tp.vrb.x, tp.vrb.y, tp.vlt.z);
tlt /= tsz;
tlb /= tsz;
trb /= tsz;
trt /= tsz;
// Geometry coordinates
vlt = new Vector3D(vl.x, vl.y, osd.Floor.plane.GetZ(vl));
vlb = new Vector3D(vl.x, vl.y, sd.Floor.plane.GetZ(vl));
vrb = new Vector3D(vr.x, vr.y, sd.Floor.plane.GetZ(vr) + planefloorbias);
vrt = new Vector3D(vr.x, vr.y, osd.Floor.plane.GetZ(vr));
TexturePlane tp = new TexturePlane();
tp.tlt = lowerunpegged ? tlb : tlt;
tp.trb = trb;
tp.trt = trt;
tp.vlt = lowerunpegged ? vlb : vlt;
tp.vrb = vrb;
tp.vrt = vrt;
// Create initial polygon, which is just a quad between floor and ceiling
WallPolygon poly = new WallPolygon();
poly.Add(new Vector3D(vl.x, vl.y, vlzf));

View file

@ -162,7 +162,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
Vector2D tsz = new Vector2D(Math.Ceiling(base.Texture.ScaledWidth / tscale.x), Math.Ceiling(base.Texture.ScaledHeight / tscale.y));
// Get texture offsets
Vector2D tof = new Vector2D(Sidedef.OffsetX, Sidedef.OffsetY) + new Vector2D(sourceside.OffsetX, sourceside.OffsetY);
//Vector2D tof = new Vector2D(Sidedef.OffsetX, Sidedef.OffsetY) + new Vector2D(sourceside.OffsetX, sourceside.OffsetY);
Vector2D tof = new Vector2D(Sidedef.OffsetX, 0.0f) + new Vector2D(0.0f, sourceside.OffsetY);
tof = tof + toffset1 + toffset2;
@ -184,35 +185,59 @@ namespace CodeImp.DoomBuilder.BuilderModes
// We choose here.
double sourcetopheight = extrafloor.VavoomType ? sourceside.Sector.FloorHeight : sourceside.Sector.CeilHeight;
double sourcebottomheight = extrafloor.VavoomType ? sourceside.Sector.CeilHeight : sourceside.Sector.FloorHeight;
// Determine texture coordinates plane as they would be in normal circumstances.
// We can then use this plane to find any texture coordinate we need.
// The logic here is the same as in the original VisualMiddleSingle (except that
// the values are stored in a TexturePlane)
// NOTE: I use a small bias for the floor height, because if the difference in
// height is 0 then the TexturePlane doesn't work!
TexturePlane tp = new TexturePlane();
double floorbias = (sourcetopheight == sourcebottomheight) ? 1.0f : 0.0f;
Vector3D vlt, vlb, vrt, vrb;
Vector2D tlt, tlb, trt, trb;
bool lowerunpegged = sourceside.Line.IsFlagSet(General.Map.Config.LowerUnpeggedFlag);
bool slopeskew = sourceside.Line.IsFlagSet(General.Map.Config.SlopeSkewFlag);
double topheight = slopeskew ? extrafloor.Ceiling.plane.GetZ(vl) : sourcetopheight;
double bottomheight = slopeskew ? extrafloor.Floor.plane.GetZ(vl) : sourcebottomheight;
double topheight2 = slopeskew ? extrafloor.Ceiling.plane.GetZ(vr) : sourcetopheight;
double bottomheight2 = slopeskew ? extrafloor.Floor.plane.GetZ(vr) : sourcebottomheight;
//float floorbias = (topheight == bottomheight) ? 1.0f : 0.0f;
//float floorbias2 = (topheight2 == bottomheight2) ? 1.0f : 0.0f;
tlt.x = tlb.x = 0;
trt.x = trb.x = Sidedef.Line.Length;
// For SRB2, invert Lower Unpegged behavior for non-skewed 3D floors
tlt.y = !(lowerunpegged ^ slopeskew) ? 0 : -(topheight - bottomheight);
trt.y = !(lowerunpegged ^ slopeskew) ? 0 : -(topheight2 - bottomheight2);
tlb.y = !(!lowerunpegged ^ slopeskew) ? 0 : (topheight - bottomheight);
trb.y = !(!lowerunpegged ^ slopeskew) ? 0 : (topheight2 - bottomheight2);
tp.trb.x = tp.tlt.x + Math.Round(Sidedef.Line.Length); //mxd. (G)ZDoom snaps texture coordinates to integral linedef length
tp.trb.y = tp.tlt.y + (sourcetopheight - sourcebottomheight) + floorbias;
// Apply texture offset
tp.tlt += tof;
tp.trb += tof;
tlt += tof;
tlb += tof;
trb += tof;
trt += tof;
// Transform pixel coordinates to texture coordinates
tp.tlt /= tsz;
tp.trb /= tsz;
// Left top and right bottom of the geometry that
tp.vlt = new Vector3D(vl.x, vl.y, sourcetopheight);
tp.vrb = new Vector3D(vr.x, vr.y, sourcebottomheight + floorbias);
// Make the right-top coordinates
tp.trt = new Vector2D(tp.trb.x, tp.tlt.y);
tp.vrt = new Vector3D(tp.vrb.x, tp.vrb.y, tp.vlt.z);
tlt /= tsz;
tlb /= tsz;
trb /= tsz;
trt /= tsz;
// Geometry coordinates
vlt = new Vector3D(vl.x, vl.y, topheight);
vlb = new Vector3D(vl.x, vl.y, bottomheight);
vrb = new Vector3D(vr.x, vr.y, bottomheight2);
vrt = new Vector3D(vr.x, vr.y, topheight2);
TexturePlane tp = new TexturePlane();
tp.tlt = lowerunpegged ? tlb : tlt;
tp.trb = trb;
tp.trt = trt;
tp.vlt = lowerunpegged ? vlb : vlt;
tp.vrb = vrb;
tp.vrt = vrt;
//mxd. Get ceiling and floor heights. Use our and neighbour sector's data
SectorData sdo = mode.GetSectorData(Sidedef.Other.Sector);

View file

@ -39,6 +39,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
#region ================== Variables
private bool repeatmidtex;
private int repetitions;
private Plane topclipplane;
private Plane bottomclipplane;
@ -46,6 +47,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
#region ================== Properties
private bool RepeatIndefinitely { get { return repeatmidtex && repetitions == 1; } }
#endregion
#region ================== Constructor / Setup
@ -153,35 +156,139 @@ namespace CodeImp.DoomBuilder.BuilderModes
// the values are stored in a TexturePlane)
// NOTE: I use a small bias for the floor height, because if the difference in
// height is 0 then the TexturePlane doesn't work!
TexturePlane tp = new TexturePlane();
Vector3D vlt, vlb, vrt, vrb;
Vector2D tlt, tlb, trt, trb;
double floorbias = (Sidedef.Sector.CeilHeight == Sidedef.Sector.FloorHeight) ? 1.0 : 0.0;
double geotop = Math.Min(Sidedef.Sector.CeilHeight, Sidedef.Other.Sector.CeilHeight);
double geobottom = Math.Max(Sidedef.Sector.FloorHeight, Sidedef.Other.Sector.FloorHeight);
double zoffset = Sidedef.Sector.CeilHeight - Sidedef.Other.Sector.CeilHeight; //mxd
double geoplanetop = Math.Min(sd.Ceiling.plane.GetZ(vl), osd.Ceiling.plane.GetZ(vl));
double geoplanebottom = Math.Max(sd.Floor.plane.GetZ(vl), osd.Floor.plane.GetZ(vl));
// When peg midtexture is set, the middle texture is bound to the bottom
if(Sidedef.Line.IsFlagSet(General.Map.Config.PegMidtextureFlag))
tp.tlt.y = tsz.y - (geotop - geobottom);
bool lowerunpegged = Sidedef.Line.IsFlagSet(General.Map.Config.LowerUnpeggedFlag);
bool pegmidtexture = Sidedef.Line.IsFlagSet(General.Map.Config.PegMidtextureFlag);
bool nomidtextureskew = Sidedef.Line.IsFlagSet(General.Map.Config.NoMidtextureSkewFlag);
double textop = nomidtextureskew ? geotop : geoplanetop;
double texbottom = nomidtextureskew ? geobottom : geoplanebottom;
if (General.Map.UDMF)
{
repeatmidtex = Sidedef.IsFlagSet("wrapmidtex") || Sidedef.Line.IsFlagSet("wrapmidtex"); //mxd
repetitions = repeatmidtex ? Sidedef.Fields.GetValue("repeatcnt", 0) + 1 : 1;
}
else if (General.Map.HEXEN)
{
repeatmidtex = Sidedef.Line.Action == 121 && (Sidedef.Line.Args[1] & 16) == 16;
repetitions = 1;
}
else
{
repeatmidtex = false;
repetitions = 1;
}
// First determine the visible portion of the texture
if (!RepeatIndefinitely)
{
// Determine top portion height
if (Sidedef.Line.IsFlagSet(General.Map.Config.PegMidtextureFlag))
textop = texbottom + tof.y + repetitions * Math.Abs(tsz.y);
else
textop += tof.y;
// Calculate bottom portion height
texbottom = textop - repetitions * Math.Abs(tsz.y);
}
else
{
if (Sidedef.Line.IsFlagSet(General.Map.Config.PegMidtextureFlag))
{
//textop = topheight;
texbottom += tof.y;
}
else
{
textop += tof.y;
//texbottom = bottomheight;
}
}
double h = Math.Min(textop, geoplanetop);
double l = Math.Max(texbottom, geoplanebottom);
double texturevpeg;
// When lower unpegged is set, the middle texture is bound to the bottom
if (pegmidtexture)
texturevpeg = repetitions * Math.Abs(tsz.y) - h + texbottom;
else
texturevpeg = textop - h;
tlt.x = tlb.x = tof.x;
trt.x = trb.x = tof.x + Sidedef.Line.Length;
tlt.y = trt.y = texturevpeg;
tlb.y = trb.y = texturevpeg + h - (l + floorbias);
double rh = h;
double rl = l;
// Correct to account for slopes
double midtextureslant;
if (nomidtextureskew)
midtextureslant = 0;
else if (pegmidtexture)
midtextureslant = osd.Floor.plane.GetZ(vl) < sd.Floor.plane.GetZ(vl)
? sd.Floor.plane.GetZ(vr) - sd.Floor.plane.GetZ(vl)
: osd.Floor.plane.GetZ(vr) - osd.Floor.plane.GetZ(vl);
else
midtextureslant = sd.Ceiling.plane.GetZ(vl) < osd.Ceiling.plane.GetZ(vl)
? sd.Ceiling.plane.GetZ(vr) - sd.Ceiling.plane.GetZ(vl)
: osd.Ceiling.plane.GetZ(vr) - osd.Ceiling.plane.GetZ(vl);
double newtextop = textop + midtextureslant;
double newtexbottom = texbottom + midtextureslant;
double highcut = geotop + (sd.Ceiling.plane.GetZ(vl) < osd.Ceiling.plane.GetZ(vl)
? sd.Ceiling.plane.GetZ(vr) - sd.Ceiling.plane.GetZ(vl)
: osd.Ceiling.plane.GetZ(vr) - osd.Ceiling.plane.GetZ(vl));
double lowcut = geobottom + (osd.Floor.plane.GetZ(vl) < sd.Floor.plane.GetZ(vl)
? sd.Floor.plane.GetZ(vr) - sd.Floor.plane.GetZ(vl)
: osd.Floor.plane.GetZ(vr) - osd.Floor.plane.GetZ(vl));
// Texture stuff
rh = Math.Min(highcut, newtextop);
rl = Math.Max(newtexbottom, lowcut);
double newtexturevpeg;
// When lower unpegged is set, the middle texture is bound to the bottom
if (pegmidtexture)
newtexturevpeg = repetitions * Math.Abs(tsz.y) - rh + newtexbottom;
else
newtexturevpeg = newtextop - rh;
trt.y = newtexturevpeg;
trb.y = newtexturevpeg + rh - (rl + floorbias);
if(zoffset > 0) tp.tlt.y -= zoffset; //mxd
tp.trb.x = tp.tlt.x + Math.Round(Sidedef.Line.Length); //mxd. (G)ZDoom snaps texture coordinates to integral linedef length
tp.trb.y = tp.tlt.y + (Sidedef.Sector.CeilHeight - (Sidedef.Sector.FloorHeight + floorbias));
// Apply texture offset
tp.tlt += tof;
tp.trb += tof;
// Transform pixel coordinates to texture coordinates
tp.tlt /= tsz;
tp.trb /= tsz;
tlt /= tsz;
tlb /= tsz;
trb /= tsz;
trt /= tsz;
// Left top and right bottom of the geometry that
tp.vlt = new Vector3D(vl.x, vl.y, Sidedef.Sector.CeilHeight);
tp.vrb = new Vector3D(vr.x, vr.y, Sidedef.Sector.FloorHeight + floorbias);
// Geometry coordinates
vlt = new Vector3D(vl.x, vl.y, h);
vlb = new Vector3D(vl.x, vl.y, l);
vrb = new Vector3D(vr.x, vr.y, rl);
vrt = new Vector3D(vr.x, vr.y, rh);
// Make the right-top coordinates
tp.trt = new Vector2D(tp.trb.x, tp.tlt.y);
tp.vrt = new Vector3D(tp.vrb.x, tp.vrb.y, tp.vlt.z);
TexturePlane tp = new TexturePlane();
tp.tlt = pegmidtexture ? tlb : tlt;
tp.trb = trb;
tp.trt = trt;
tp.vlt = pegmidtexture ? vlb : vlt;
tp.vrb = vrb;
tp.vrt = vrt;
// Keep top and bottom planes for intersection testing
top = sd.Ceiling.plane;
@ -209,36 +316,44 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Determine if we should repeat the middle texture. In UDMF this is done with a flag, in Hexen with
// a argument to the 121:Line_SetIdentification. See https://www.zdoom.org/w/index.php?title=Line_SetIdentification
if (General.Map.UDMF)
repeatmidtex = Sidedef.IsFlagSet("wrapmidtex") || Sidedef.Line.IsFlagSet("wrapmidtex"); //mxd
else if (General.Map.HEXEN)
repeatmidtex = Sidedef.Line.Action == 121 && (Sidedef.Line.Args[1] & 16) == 16;
else
repeatmidtex = false;
if(!repeatmidtex)
// First determine the visible portion of the texture
// NOTE: this is done earlier for SRB2 since it's needed earlier
// Create crop planes (we also need these for intersection testing)
if (!nomidtextureskew)
{
// First determine the visible portion of the texture
double textop;
if (pegmidtexture)
{
bottomclipplane = sd.Floor.plane.GetZ(vl) > osd.Floor.plane.GetZ(vl) ? sd.Floor.plane : osd.Floor.plane;
Vector3D up = new Vector3D(0f, 0f, texbottom - bottomclipplane.GetZ(vl));
bottomclipplane.Offset -= Vector3D.DotProduct(up, bottomclipplane.Normal);
// Determine top portion height
if(Sidedef.Line.IsFlagSet(General.Map.Config.PegMidtextureFlag))
textop = geobottom + tof.y + Math.Abs(tsz.y);
else
textop = geotop + tof.y;
topclipplane = bottomclipplane.GetInverted();
Vector3D up2 = new Vector3D(0f, 0f, textop - texbottom);
topclipplane.Offset -= Vector3D.DotProduct(up2, topclipplane.Normal);
}
else //Skew according to ceiling
{
topclipplane = sd.Ceiling.plane.GetZ(vl) < osd.Ceiling.plane.GetZ(vl) ? sd.Ceiling.plane : osd.Ceiling.plane;
Vector3D up = new Vector3D(0f, 0f, textop - topclipplane.GetZ(vl));
topclipplane.Offset -= Vector3D.DotProduct(up, topclipplane.Normal);
// Calculate bottom portion height
double texbottom = textop - Math.Abs(tsz.y);
// Create crop planes (we also need these for intersection testing)
bottomclipplane = topclipplane.GetInverted();
Vector3D down = new Vector3D(0f, 0f, texbottom - textop);
bottomclipplane.Offset -= Vector3D.DotProduct(down, bottomclipplane.Normal);
}
}
else
{
topclipplane = new Plane(new Vector3D(0, 0, -1), textop);
bottomclipplane = new Plane(new Vector3D(0, 0, 1), -texbottom);
// Crop polygon by these heights
CropPoly(ref poly, topclipplane, true);
CropPoly(ref poly, bottomclipplane, true);
}
// Crop polygon by these heights
CropPoly(ref poly, topclipplane, true);
CropPoly(ref poly, bottomclipplane, true);
//mxd. In(G)ZDoom, middle sidedef parts are not clipped by extrafloors of any type...
List<WallPolygon> polygons = new List<WallPolygon> { poly };
//ClipExtraFloors(polygons, sd.ExtraFloors, true); //mxd
@ -282,13 +397,13 @@ namespace CodeImp.DoomBuilder.BuilderModes
// This performs a fast test in object picking
public override bool PickFastReject(Vector3D from, Vector3D to, Vector3D dir)
{
if(!repeatmidtex)
{
// When the texture is not repeated, leave when outside crop planes
//if(!RepeatIndefinitely)
//{
// When the texture is not repeated indefinitely, leave when outside crop planes
if((pickintersect.z < bottomclipplane.GetZ(pickintersect)) ||
(pickintersect.z > topclipplane.GetZ(pickintersect)))
return false;
}
//}
return base.PickFastReject(from, to, dir);
}
@ -316,7 +431,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
% imageWidth);
int oy;
if (repeatmidtex)
/*if (RepeatIndefinitely)
{
bool pegbottom = Sidedef.Line.IsFlagSet(General.Map.Config.PegMidtextureFlag);
double zoffset = (pegbottom ? Sidedef.Sector.FloorHeight : Sidedef.Sector.CeilHeight);
@ -325,10 +440,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
% imageHeight);
}
else
{
{*/
double zoffset = bottomclipplane.GetZ(pickintersect);
oy = (int)Math.Ceiling(((pickintersect.z - zoffset) * UniFields.GetFloat(Sidedef.Fields, "scaley_mid", 1.0f) / texscale.y) % imageHeight);
}
//}
// Make sure offsets are inside of texture dimensions...
if (ox < 0) ox += imageWidth;

View file

@ -139,31 +139,76 @@ namespace CodeImp.DoomBuilder.BuilderModes
// the values are stored in a TexturePlane)
// NOTE: I use a small bias for the floor height, because if the difference in
// height is 0 then the TexturePlane doesn't work!
TexturePlane tp = new TexturePlane();
double floorbias = (Sidedef.Sector.CeilHeight == Sidedef.Sector.FloorHeight) ? 1.0 : 0.0;
if(Sidedef.Line.IsFlagSet(General.Map.Config.PegMidtextureFlag))
Vector3D vlt, vlb, vrt, vrb;
Vector2D tlt, tlb, trt, trb;
double texturevpeg = 0;
double floorbias = (Sidedef.Sector.CeilHeight == Sidedef.Sector.FloorHeight) ? 1.0f : 0.0f;
bool lowerunpegged = Sidedef.Line.IsFlagSet(General.Map.Config.LowerUnpeggedFlag);
bool nomidtextureskew = Sidedef.Line.IsFlagSet(General.Map.Config.NoMidtextureSkewFlag);
if (lowerunpegged)
{
// When peg midtexture is set, the middle texture is bound to the bottom
tp.tlt.y = tsz.y - (Sidedef.Sector.CeilHeight - Sidedef.Sector.FloorHeight);
// When lower unpegged is set, the middle texture is bound to the bottom
if (!nomidtextureskew)
{
texturevpeg = tsz.y - (sd.Ceiling.plane.GetZ(vl) - sd.Floor.plane.GetZ(vl));
}
else
{
texturevpeg = tsz.y - (Sidedef.Sector.CeilHeight - Sidedef.Sector.FloorHeight);
}
}
tp.trb.x = tp.tlt.x + Math.Round(Sidedef.Line.Length); //mxd. (G)ZDoom snaps texture coordinates to integral linedef length
tp.trb.y = tp.tlt.y + (Sidedef.Sector.CeilHeight - (Sidedef.Sector.FloorHeight + floorbias));
tlt.x = tlb.x = 0;
trt.x = trb.x = Sidedef.Line.Length;
tlt.y = trt.y = texturevpeg;
tlb.y = trb.y = texturevpeg + (Sidedef.Sector.CeilHeight - (Sidedef.Sector.FloorHeight + floorbias));
// Texture correction for slopes
if (nomidtextureskew)
{
tlt.y += Sidedef.Sector.CeilHeight - sd.Ceiling.plane.GetZ(vl);
trt.y += Sidedef.Sector.CeilHeight - sd.Ceiling.plane.GetZ(vr);
tlb.y += Sidedef.Sector.FloorHeight - sd.Floor.plane.GetZ(vl);
trb.y += Sidedef.Sector.FloorHeight - sd.Floor.plane.GetZ(vr);
}
else if (lowerunpegged)
{
tlt.y = tlb.y + sd.Floor.plane.GetZ(vl) - sd.Ceiling.plane.GetZ(vl);
trt.y = trb.y + sd.Floor.plane.GetZ(vr) - sd.Ceiling.plane.GetZ(vr);
}
else
{
tlb.y = tlt.y - (sd.Floor.plane.GetZ(vl) - sd.Ceiling.plane.GetZ(vl));
trb.y = trt.y - (sd.Floor.plane.GetZ(vr) - sd.Ceiling.plane.GetZ(vr));
}
// Apply texture offset
tp.tlt += tof;
tp.trb += tof;
tlt += tof;
tlb += tof;
trb += tof;
trt += tof;
// Transform pixel coordinates to texture coordinates
tp.tlt /= tsz;
tp.trb /= tsz;
// Left top and right bottom of the geometry that
tp.vlt = new Vector3D(vl.x, vl.y, Sidedef.Sector.CeilHeight);
tp.vrb = new Vector3D(vr.x, vr.y, Sidedef.Sector.FloorHeight + floorbias);
// Make the right-top coordinates
tp.trt = new Vector2D(tp.trb.x, tp.tlt.y);
tp.vrt = new Vector3D(tp.vrb.x, tp.vrb.y, tp.vlt.z);
tlt /= tsz;
tlb /= tsz;
trb /= tsz;
trt /= tsz;
// Geometry coordinates
vlt = new Vector3D(vl.x, vl.y, sd.Ceiling.plane.GetZ(vl));
vlb = new Vector3D(vl.x, vl.y, sd.Floor.plane.GetZ(vl) + floorbias);
vrb = new Vector3D(vr.x, vr.y, sd.Floor.plane.GetZ(vr));
vrt = new Vector3D(vr.x, vr.y, sd.Ceiling.plane.GetZ(vr));
TexturePlane tp = new TexturePlane();
tp.tlt = lowerunpegged ? tlb : tlt;
tp.trb = trb;
tp.trt = trt;
tp.vlt = lowerunpegged ? vlb : vlt;
tp.vrb = vrb;
tp.vrt = vrt;
// Get ceiling and floor heights
double fl = sd.Floor.plane.GetZ(vl);

View file

@ -154,32 +154,85 @@ namespace CodeImp.DoomBuilder.BuilderModes
// the values are stored in a TexturePlane)
// NOTE: I use a small bias for the floor height, because if the difference in
// height is 0 then the TexturePlane doesn't work!
TexturePlane tp = new TexturePlane();
Vector3D vlt, vlb, vrt, vrb;
Vector2D tlt, tlb, trt, trb;
double ceilbias = (Sidedef.Other.Sector.CeilHeight == Sidedef.Sector.CeilHeight) ? 1.0 : 0.0;
if(!Sidedef.Line.IsFlagSet(General.Map.Config.UpperUnpeggedFlag))
double planeceilbias = (Math.Abs(osd.Ceiling.plane.GetZ(vr) - sd.Ceiling.plane.GetZ(vr)) < 0.5) ? 1.0 : 0.0;
double texturevpeg = 0;
bool upperunpegged = Sidedef.Line.IsFlagSet(General.Map.Config.UpperUnpeggedFlag);
bool slopeskew = Sidedef.Line.IsFlagSet(General.Map.Config.SlopeSkewFlag);
if (!upperunpegged)
{
// When lower unpegged is set, the lower texture is bound to the bottom
tp.tlt.y = tsz.y - (Sidedef.Sector.CeilHeight - Sidedef.Other.Sector.CeilHeight);
if (slopeskew)
{
texturevpeg = osd.Ceiling.plane.GetZ(vl) + tsz.y - sd.Ceiling.plane.GetZ(vl);
}
else
{
texturevpeg = tsz.y - ((float)Sidedef.Sector.CeilHeight - Sidedef.Other.Sector.CeilHeight);
}
}
tp.trb.x = tp.tlt.x + Math.Round(Sidedef.Line.Length); //mxd. (G)ZDoom snaps texture coordinates to integral linedef length
tp.trb.y = tp.tlt.y + (Sidedef.Sector.CeilHeight - (Sidedef.Other.Sector.CeilHeight + ceilbias));
tlt.x = tlb.x = 0;
trt.x = trb.x = Sidedef.Line.Length;
tlt.y = trt.y = texturevpeg;
tlb.y = trb.y = texturevpeg + (Sidedef.Sector.CeilHeight - (Sidedef.Other.Sector.CeilHeight + ceilbias));
// Adjust texture y value for sloped walls
if (!slopeskew)
{
// Unskewed
tlt.y -= sd.Ceiling.plane.GetZ(vl) - Sidedef.Sector.CeilHeight;
trt.y -= sd.Ceiling.plane.GetZ(vr) - Sidedef.Sector.CeilHeight;
tlb.y -= osd.Ceiling.plane.GetZ(vl) - Sidedef.Other.Sector.CeilHeight;
trb.y -= osd.Ceiling.plane.GetZ(vr) - Sidedef.Other.Sector.CeilHeight;
}
else if (upperunpegged)
{
// Skewed by top
tlb.y = texturevpeg + sd.Ceiling.plane.GetZ(vl) - osd.Ceiling.plane.GetZ(vl);
trb.y = texturevpeg + sd.Ceiling.plane.GetZ(vr) - osd.Ceiling.plane.GetZ(vr);
}
else
{
// Skewed by bottom
tlb.y = texturevpeg + sd.Ceiling.plane.GetZ(vl) - osd.Ceiling.plane.GetZ(vl);
trb.y = tlb.y;
tlt.y = tlb.y - (sd.Ceiling.plane.GetZ(vl) - osd.Ceiling.plane.GetZ(vl));
trt.y = trb.y - (sd.Ceiling.plane.GetZ(vr) - osd.Ceiling.plane.GetZ(vr));
}
if (Math.Abs(trb.y - trt.y) < 0.5f) trb.y = trt.y - 1.0f;
// Apply texture offset
tp.tlt += tof;
tp.trb += tof;
tlt += tof;
tlb += tof;
trb += tof;
trt += tof;
// Transform pixel coordinates to texture coordinates
tp.tlt /= tsz;
tp.trb /= tsz;
// Left top and right bottom of the geometry that
tp.vlt = new Vector3D(vl.x, vl.y, Sidedef.Sector.CeilHeight);
tp.vrb = new Vector3D(vr.x, vr.y, Sidedef.Other.Sector.CeilHeight + ceilbias);
// Make the right-top coordinates
tp.trt = new Vector2D(tp.trb.x, tp.tlt.y);
tp.vrt = new Vector3D(tp.vrb.x, tp.vrb.y, tp.vlt.z);
tlt /= tsz;
tlb /= tsz;
trb /= tsz;
trt /= tsz;
// Geometry coordinates
vlt = new Vector3D(vl.x, vl.y, sd.Ceiling.plane.GetZ(vl));
vlb = new Vector3D(vl.x, vl.y, osd.Ceiling.plane.GetZ(vl));
vrb = new Vector3D(vr.x, vr.y, osd.Ceiling.plane.GetZ(vr) + planeceilbias);
vrt = new Vector3D(vr.x, vr.y, sd.Ceiling.plane.GetZ(vr));
TexturePlane tp = new TexturePlane();
tp.tlt = Sidedef.Line.IsFlagSet(General.Map.Config.UpperUnpeggedFlag) ? tlt : tlb;
tp.trb = trb;
tp.trt = trt;
tp.vlt = Sidedef.Line.IsFlagSet(General.Map.Config.UpperUnpeggedFlag) ? vlt : vlb;
tp.vrb = vrb;
tp.vrt = vrt;
// Create initial polygon, which is just a quad between floor and ceiling
WallPolygon poly = new WallPolygon();
poly.Add(new Vector3D(vl.x, vl.y, sd.Floor.plane.GetZ(vl)));