Visual Mode: things inside self-referencing sectors are now displayed at the correct height

This commit is contained in:
biwa 2021-04-05 19:15:14 +02:00
parent fe71e53edc
commit 6c8a3cb50b
3 changed files with 75 additions and 17 deletions

View file

@ -546,6 +546,9 @@ namespace CodeImp.DoomBuilder.Map
// This checks if the given point is inside the sector polygon
// See: http://paulbourke.net/geometry/polygonmesh/index.html#insidepoly
// This checks for the linedefs instead of the sidedefs, since self-referencing sectors
// will never result in an odd number of intersections when using sidedefs, since both
// sidedefs of the outer linedef belong to the same sector
public bool Intersect(Vector2D p) { return Intersect(p, true); }
public bool Intersect(Vector2D p, bool countontopastrue)
{
@ -554,13 +557,17 @@ namespace CodeImp.DoomBuilder.Map
uint c = 0;
Vector2D v1, v2;
HashSet<Linedef> linedefs = new HashSet<Linedef>(sidedefs.Count);
foreach (Sidedef sd in sidedefs)
linedefs.Add(sd.Line);
// Go for all sidedefs
foreach(Sidedef sd in sidedefs)
// Go for all linedefs
foreach(Linedef ld in linedefs)
{
// Get vertices
v1 = sd.Line.Start.Position;
v2 = sd.Line.End.Position;
v1 = ld.Start.Position;
v2 = ld.End.Position;
//mxd. On top of a vertex?
if(p == v1 || p == v2) return countontopastrue;

View file

@ -273,19 +273,46 @@ namespace CodeImp.DoomBuilder.Map
public void DetermineSector(BlockMap<BlockEntry> blockmap)
{
BlockEntry be = blockmap.GetBlockAt(pos);
List<Sector> sectors = new List<Sector>(1);
foreach (Sector s in be.Sectors)
if (s.Intersect(pos))
{
sector = s;
return;
}
sectors.Add(s);
if(sectors.Count == 0)
{
sector = null;
}
if (sectors.Count == 1)
{
sector = sectors[0];
}
else
{
// Having multiple intersections indicates that there are self-referencing sectors in this spot.
// In this case we have to check which side of the nearest linedef pos is on, and then use that sector
HashSet<Linedef> linedefs = new HashSet<Linedef>(sectors[0].Sidedefs.Count * sectors.Count);
foreach (Sector s in sectors)
foreach (Sidedef sd in s.Sidedefs)
linedefs.Add(sd.Line);
Linedef nearest = MapSet.NearestLinedef(linedefs, pos);
double d = nearest.SideOfLine(pos);
if (d <= 0.0 && nearest.Front != null)
sector = nearest.Front.Sector;
else if (nearest.Back != null)
sector = nearest.Back.Sector;
else
sector = null;
}
}
// This determines which sector the thing is in and links it
public void DetermineSector(VisualBlockMap blockmap)
{
sector = blockmap.GetSectorAt(pos);
sector = blockmap.GetSectorAt(pos);
}
// This translates the flags into UDMF fields

View file

@ -76,16 +76,40 @@ namespace CodeImp.DoomBuilder.VisualModes
public Sector GetSectorAt(Vector2D pos)
{
foreach (VisualBlockEntry e in GetBlocks(pos))
{
List<Sector> sectors = new List<Sector>(1);
foreach (VisualBlockEntry e in GetBlocks(pos))
foreach (Sector s in e.Sectors)
{
if (s.Intersect(pos))
{
return s;
}
}
}
sectors.Add(s);
if (sectors.Count == 0)
{
return null;
}
else if (sectors.Count == 1)
{
return sectors[0];
}
else
{
// Having multiple intersections indicates that there are self-referencing sectors in this spot.
// In this case we have to check which side of the nearest linedef pos is on, and then use that sector
HashSet<Linedef> linedefs = new HashSet<Linedef>(sectors[0].Sidedefs.Count * sectors.Count);
foreach (Sector s in sectors)
foreach (Sidedef sd in s.Sidedefs)
linedefs.Add(sd.Line);
Linedef nearest = MapSet.NearestLinedef(linedefs, pos);
double d = nearest.SideOfLine(pos);
if (d <= 0.0 && nearest.Front != null)
return nearest.Front.Sector;
else if (nearest.Back != null)
return nearest.Back.Sector;
}
return null;
}