diff --git a/Build/Configurations/Includes/RingRacers_misc.cfg b/Build/Configurations/Includes/RingRacers_misc.cfg index 5f479834ddf342ebb686eacd8504c16ccb0d7e66..ac92eec7eb18dc093bc5edd2d349baec0bbf331a 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/Build/Configurations/Includes/SRB222_misc.cfg b/Build/Configurations/Includes/SRB222_misc.cfg index 65ce70c6005560087d39fc8e1c24c1d68ed38314..d2128ad9acc5c0c2014e0a46c38602eec600f741 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 a30ef88e3e4674ef9ed204d55427ccba9c0330ec..7ab4968a895be23aaaffc03454c726b539b54285 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 325d38549e77ec5c1c39814cb5f60dcb3f06cacc..16fa8dfb8b64639bbc31c84a0be7b37c837c7d7b 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 aa8645348dece9b61d5d5334ca37e5bc0a137fe2..bcd389efe004fa378d2e4849d4ed2f4e6d8661b0 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 e958a2d8c9d6e45d7b4011b7857ea4eb6d1f0c60..589c59c1a0bb3f2ee2da9aeba420609cb4483a26 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 + private bool RepeatIndefinitely { get { return repeatmidtex && repetitions == 1; } } + #endregion #region ================== Constructor / Setup @@ -153,35 +156,141 @@ 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; + Vector3D vlt, vlb, vrt, vrb; + Vector2D tlt, tlb, trt, trb; 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; + + 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; + } - // Apply texture offset - tp.tlt += tof; - tp.trb += tof; + // 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; + // 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 + leftfloorbias); + + // 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 + double rh = Math.Min(highcut, newtextop); + double 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; + + // 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 + rightfloorbias); + // 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 + leftfloorbias); + vrb = new Vector3D(vr.x, vr.y, rl + rightfloorbias); + 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 +316,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 @@ -316,11 +430,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); } diff --git a/Source/Plugins/BuilderModes/VisualModes/VisualMiddleSingle.cs b/Source/Plugins/BuilderModes/VisualModes/VisualMiddleSingle.cs index c9d75e5b08818607f4de9a18aedea6cddd842090..c045e30a7460645562b254c41ad95fc106050e33 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 3e09a375ccbcd13b7046018d5fb03cc4e1b9ae79..4b300b68c7b8cedbb4c7960a74fc2e6b66b054b5 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)));