From c6f043d908f55883192e140e1427ed9ac7941644 Mon Sep 17 00:00:00 2001 From: spherallic <spherallic@gmail.com> Date: Fri, 26 May 2023 13:26:15 +0200 Subject: [PATCH 1/4] Implement proper texture skewing in Visual Mode --- Build/Configurations/Includes/SRB222_misc.cfg | 4 + Source/Core/Config/GameConfiguration.cs | 8 + .../BuilderModes/VisualModes/VisualLower.cs | 97 ++++++--- .../VisualModes/VisualMiddle3D.cs | 67 ++++-- .../VisualModes/VisualMiddleDouble.cs | 197 ++++++++++++++---- .../VisualModes/VisualMiddleSingle.cs | 87 ++++++-- .../BuilderModes/VisualModes/VisualUpper.cs | 93 +++++++-- 7 files changed, 423 insertions(+), 130 deletions(-) diff --git a/Build/Configurations/Includes/SRB222_misc.cfg b/Build/Configurations/Includes/SRB222_misc.cfg index 65ce70c60..d2128ad9a 100644 --- a/Build/Configurations/Includes/SRB222_misc.cfg +++ b/Build/Configurations/Includes/SRB222_misc.cfg @@ -595,6 +595,8 @@ speciallinedefs impassableflag = 1; upperunpeggedflag = 8; lowerunpeggedflag = 16; + slopeskewflag = 32; + nomidtextureskewflag = 128; repeatmidtextureflag = 1024; pegmidtextureflag = 256; } @@ -609,6 +611,8 @@ speciallinedefs_udmf lowerunpeggedflag = "dontpegbottom"; repeatmidtextureflag = "wrapmidtex"; pegmidtextureflag = "midpeg"; + slopeskewflag = "skewtd"; + nomidtextureskewflag = "noskew"; } scriptlumpnames diff --git a/Source/Core/Config/GameConfiguration.cs b/Source/Core/Config/GameConfiguration.cs index a30ef88e3..7ab4968a8 100755 --- a/Source/Core/Config/GameConfiguration.cs +++ b/Source/Core/Config/GameConfiguration.cs @@ -78,6 +78,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; @@ -242,6 +244,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; } } @@ -521,6 +525,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()); diff --git a/Source/Plugins/BuilderModes/VisualModes/VisualLower.cs b/Source/Plugins/BuilderModes/VisualModes/VisualLower.cs index 325d38549..16fa8dfb8 100755 --- a/Source/Plugins/BuilderModes/VisualModes/VisualLower.cs +++ b/Source/Plugins/BuilderModes/VisualModes/VisualLower.cs @@ -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)); diff --git a/Source/Plugins/BuilderModes/VisualModes/VisualMiddle3D.cs b/Source/Plugins/BuilderModes/VisualModes/VisualMiddle3D.cs index aa8645348..bcd389efe 100755 --- a/Source/Plugins/BuilderModes/VisualModes/VisualMiddle3D.cs +++ b/Source/Plugins/BuilderModes/VisualModes/VisualMiddle3D.cs @@ -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); diff --git a/Source/Plugins/BuilderModes/VisualModes/VisualMiddleDouble.cs b/Source/Plugins/BuilderModes/VisualModes/VisualMiddleDouble.cs index e958a2d8c..56bd62863 100755 --- a/Source/Plugins/BuilderModes/VisualModes/VisualMiddleDouble.cs +++ b/Source/Plugins/BuilderModes/VisualModes/VisualMiddleDouble.cs @@ -153,35 +153,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); - - 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)); + 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; - // Apply texture offset - tp.tlt += tof; - tp.trb += tof; + 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); + // 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; @@ -207,38 +311,43 @@ namespace CodeImp.DoomBuilder.BuilderModes CropPoly(ref poly, osd.Ceiling.plane, true); CropPoly(ref poly, osd.Floor.plane, true); - // 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; + // First determine the visible portion of the texture + // NOTE: this is done earlier for SRB2 since it's needed earlier - if(!repeatmidtex) + // Create crop planes (we also need these for intersection testing) + if (!nomidtextureskew) { - // First determine the visible portion of the texture - double textop; - - // 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; + 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); - // Calculate bottom portion height - double texbottom = textop - Math.Abs(tsz.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); - // 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 diff --git a/Source/Plugins/BuilderModes/VisualModes/VisualMiddleSingle.cs b/Source/Plugins/BuilderModes/VisualModes/VisualMiddleSingle.cs index c9d75e5b0..c045e30a7 100755 --- a/Source/Plugins/BuilderModes/VisualModes/VisualMiddleSingle.cs +++ b/Source/Plugins/BuilderModes/VisualModes/VisualMiddleSingle.cs @@ -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); diff --git a/Source/Plugins/BuilderModes/VisualModes/VisualUpper.cs b/Source/Plugins/BuilderModes/VisualModes/VisualUpper.cs index 3e09a375c..4b300b68c 100755 --- a/Source/Plugins/BuilderModes/VisualModes/VisualUpper.cs +++ b/Source/Plugins/BuilderModes/VisualModes/VisualUpper.cs @@ -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))); -- GitLab From 4d9f6ee72980374782e7a798e95dacbdaefcb7f0 Mon Sep 17 00:00:00 2001 From: Dante Helmore <frostu8@protonmail.com> Date: Sun, 16 Feb 2025 18:33:08 -0800 Subject: [PATCH 2/4] restore texture repeats --- Build/Configurations/Includes/RingRacers_misc.cfg | 4 ++++ .../BuilderModes/VisualModes/VisualMiddleDouble.cs | 9 ++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Build/Configurations/Includes/RingRacers_misc.cfg b/Build/Configurations/Includes/RingRacers_misc.cfg index 5f479834d..ac92eec7e 100644 --- a/Build/Configurations/Includes/RingRacers_misc.cfg +++ b/Build/Configurations/Includes/RingRacers_misc.cfg @@ -904,6 +904,8 @@ speciallinedefs lowerunpeggedflag = 16; repeatmidtextureflag = 1024; pegmidtextureflag = 256; + slopeskewflag = 32; + nomidtextureskewflag = 128; } speciallinedefs_udmf @@ -916,6 +918,8 @@ speciallinedefs_udmf lowerunpeggedflag = "dontpegbottom"; repeatmidtextureflag = "wrapmidtex"; pegmidtextureflag = "midpeg"; + slopeskewflag = "skewtd"; + nomidtextureskewflag = "noskew"; } // Texture sources diff --git a/Source/Plugins/BuilderModes/VisualModes/VisualMiddleDouble.cs b/Source/Plugins/BuilderModes/VisualModes/VisualMiddleDouble.cs index 56bd62863..d4521336b 100755 --- a/Source/Plugins/BuilderModes/VisualModes/VisualMiddleDouble.cs +++ b/Source/Plugins/BuilderModes/VisualModes/VisualMiddleDouble.cs @@ -38,6 +38,7 @@ namespace CodeImp.DoomBuilder.BuilderModes #region ================== Variables + private int repetitions; private bool repeatmidtex; private Plane topclipplane; private Plane bottomclipplane; @@ -46,6 +47,8 @@ namespace CodeImp.DoomBuilder.BuilderModes #region ================== Properties + public bool RepeatIndefinitely { get { return repeatmidtex; } } + #endregion #region ================== Constructor / Setup @@ -425,11 +428,11 @@ 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); - oy = (int)Math.Floor(((pickintersect.z - zoffset) * UniFields.GetFloat(Sidedef.Fields, "scaley_mid", 1.0f) / texscale.y + double zoffset = (pegbottom ? bottomclipplane.GetZ(pickintersect) : topclipplane.GetZ(pickintersect)); + oy = (int)Math.Ceiling(((pickintersect.z - zoffset) * UniFields.GetFloat(Sidedef.Fields, "scaley_mid", 1.0f) / texscale.y - ((Sidedef.OffsetY - UniFields.GetFloat(Sidedef.Fields, "offsety_mid")) / imgscale.y)) % imageHeight); } -- GitLab From 191bceaf3f7d0e08c169d54d006d279ebd788c54 Mon Sep 17 00:00:00 2001 From: Dante Helmore <frostu8@protonmail.com> Date: Sun, 16 Feb 2025 19:39:14 -0800 Subject: [PATCH 3/4] fix `RepeatIndefinitely` property --- Source/Plugins/BuilderModes/VisualModes/VisualMiddleDouble.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Plugins/BuilderModes/VisualModes/VisualMiddleDouble.cs b/Source/Plugins/BuilderModes/VisualModes/VisualMiddleDouble.cs index d4521336b..43c04b34d 100755 --- a/Source/Plugins/BuilderModes/VisualModes/VisualMiddleDouble.cs +++ b/Source/Plugins/BuilderModes/VisualModes/VisualMiddleDouble.cs @@ -47,7 +47,7 @@ namespace CodeImp.DoomBuilder.BuilderModes #region ================== Properties - public bool RepeatIndefinitely { get { return repeatmidtex; } } + private bool RepeatIndefinitely { get { return repeatmidtex && repetitions == 1; } } #endregion -- GitLab From 125a07dc850383a6004399da2eb64ce13f686011 Mon Sep 17 00:00:00 2001 From: Dante Helmore <frostu8@protonmail.com> Date: Mon, 17 Feb 2025 13:45:18 -0800 Subject: [PATCH 4/4] split floor bias for VisualMiddleDouble --- .../VisualModes/VisualMiddleDouble.cs | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/Source/Plugins/BuilderModes/VisualModes/VisualMiddleDouble.cs b/Source/Plugins/BuilderModes/VisualModes/VisualMiddleDouble.cs index 43c04b34d..589c59c1a 100755 --- a/Source/Plugins/BuilderModes/VisualModes/VisualMiddleDouble.cs +++ b/Source/Plugins/BuilderModes/VisualModes/VisualMiddleDouble.cs @@ -158,7 +158,6 @@ namespace CodeImp.DoomBuilder.BuilderModes // height is 0 then the TexturePlane doesn't work! 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 geoplanetop = Math.Min(sd.Ceiling.plane.GetZ(vl), osd.Ceiling.plane.GetZ(vl)); @@ -223,13 +222,13 @@ namespace CodeImp.DoomBuilder.BuilderModes else texturevpeg = textop - h; + // If the difference in height is zero, TexturePlane works funkily + double leftfloorbias = Math.Abs(h - l) <= double.Epsilon ? 1.0 : 0.0; + 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; + tlb.y = trb.y = texturevpeg + h - (l + leftfloorbias); // Correct to account for slopes double midtextureslant; @@ -256,8 +255,8 @@ namespace CodeImp.DoomBuilder.BuilderModes : osd.Floor.plane.GetZ(vr) - osd.Floor.plane.GetZ(vl)); // Texture stuff - rh = Math.Min(highcut, newtextop); - rl = Math.Max(newtexbottom, lowcut); + double rh = Math.Min(highcut, newtextop); + double rl = Math.Max(newtexbottom, lowcut); double newtexturevpeg; @@ -267,8 +266,11 @@ namespace CodeImp.DoomBuilder.BuilderModes else newtexturevpeg = newtextop - rh; + // If the difference in height is zero, TexturePlane works funkily + double rightfloorbias = Math.Abs(rh - rl) <= double.Epsilon ? 1.0 : 0.0; + trt.y = newtexturevpeg; - trb.y = newtexturevpeg + rh - (rl + floorbias); + trb.y = newtexturevpeg + rh - (rl + rightfloorbias); // Transform pixel coordinates to texture coordinates tlt /= tsz; @@ -278,8 +280,8 @@ namespace CodeImp.DoomBuilder.BuilderModes // 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); + vlb = new Vector3D(vl.x, vl.y, l + leftfloorbias); + vrb = new Vector3D(vr.x, vr.y, rl + rightfloorbias); vrt = new Vector3D(vr.x, vr.y, rh); TexturePlane tp = new TexturePlane(); -- GitLab