Added, Game configurations: added "ignoreddirectories" parameter. It lists directory names to be ignored when loading PK3/PK7/Directory resources.

Added, Game configurations: added "ignoredextensions" parameter. It lists file extensions to be ignored when loading PK3/PK7/Directory resources.
Updated: sector triangulation logic now works ~20% faster.
Changed: a case when a pk3/pk7 archive contains several entries with identical filename is now treated as a warning, not as an error.
Fixed, Visual mode: absolute floor/ceiling brightness should not be affected by brightness transfer effects (like 3d floors).
Fixed, Draw Lines mode: in some cases unclosed sectors were created when several points were successively drawn at the same location.
Updated documentation.
This commit is contained in:
MaxED 2016-10-24 19:19:11 +00:00 committed by spherallic
parent 50a547a570
commit 41ae6b3c55
3 changed files with 91 additions and 53 deletions

View file

@ -374,18 +374,18 @@ namespace CodeImp.DoomBuilder.Geometry
Vertex found = null; Vertex found = null;
// Go for all sides to find the right-most side // Go for all sides to find the right-most side
foreach(KeyValuePair<Sidedef, bool> sd in sides) foreach(Sidedef sd in sides.Keys)
{ {
// First found? // First found?
if((found == null) && !ignores.ContainsKey(sd.Key.Line.Start)) found = sd.Key.Line.Start; if((found == null) && !ignores.ContainsKey(sd.Line.Start)) found = sd.Line.Start;
if((found == null) && !ignores.ContainsKey(sd.Key.Line.End)) found = sd.Key.Line.End; if((found == null) && !ignores.ContainsKey(sd.Line.End)) found = sd.Line.End;
// Compare? // Compare?
if(found != null) if(found != null)
{ {
// Check if more to the right than the previous found // Check if more to the right than the previous found
if((sd.Key.Line.Start.Position.x > found.Position.x) && !ignores.ContainsKey(sd.Key.Line.Start)) found = sd.Key.Line.Start; if((sd.Line.Start.Position.x > found.Position.x) && !ignores.ContainsKey(sd.Line.Start)) found = sd.Line.Start;
if((sd.Key.Line.End.Position.x > found.Position.x) && !ignores.ContainsKey(sd.Key.Line.End)) found = sd.Key.Line.End; if((sd.Line.End.Position.x > found.Position.x) && !ignores.ContainsKey(sd.Line.End)) found = sd.Line.End;
} }
} }
@ -779,11 +779,16 @@ namespace CodeImp.DoomBuilder.Geometry
// This checks if a given ear is a valid (no intersections from reflex vertices) // This checks if a given ear is a valid (no intersections from reflex vertices)
private static bool CheckValidEar(EarClipVertex[] t, LinkedList<EarClipVertex> reflexes) private static bool CheckValidEar(EarClipVertex[] t, LinkedList<EarClipVertex> reflexes)
{ {
//mxd
Vector2D pos0 = t[0].Position;
Vector2D pos1 = t[1].Position;
Vector2D pos2 = t[2].Position;
// Go for all reflex vertices // Go for all reflex vertices
foreach(EarClipVertex rv in reflexes) foreach(EarClipVertex rv in reflexes)
{ {
// Not one of the triangle corners? // Not one of the triangle corners?
if((rv.Position != t[0].Position) && (rv.Position != t[1].Position) && (rv.Position != t[2].Position)) if((rv.Position != pos0) && (rv.Position != pos1) && (rv.Position != pos2))
{ {
// Return false on intersection // Return false on intersection
if(PointInsideTriangle(t, rv.MainListNode)) return false; if(PointInsideTriangle(t, rv.MainListNode)) return false;
@ -797,11 +802,12 @@ namespace CodeImp.DoomBuilder.Geometry
// This returns the 3-vertex array triangle for an ear // This returns the 3-vertex array triangle for an ear
private static EarClipVertex[] GetTriangle(EarClipVertex v) private static EarClipVertex[] GetTriangle(EarClipVertex v)
{ {
EarClipVertex[] t = new EarClipVertex[3]; return new []
t[0] = (v.MainListNode.Previous == null) ? v.MainListNode.List.Last.Value : v.MainListNode.Previous.Value; {
t[1] = v; (v.MainListNode.Previous == null) ? v.MainListNode.List.Last.Value : v.MainListNode.Previous.Value,
t[2] = (v.MainListNode.Next == null) ? v.MainListNode.List.First.Value : v.MainListNode.Next.Value; v,
return t; (v.MainListNode.Next == null) ? v.MainListNode.List.First.Value : v.MainListNode.Next.Value
};
} }
// This checks if a vertex is reflex (corner > 180 deg) or convex (corner < 180 deg) // This checks if a vertex is reflex (corner > 180 deg) or convex (corner < 180 deg)
@ -820,18 +826,23 @@ namespace CodeImp.DoomBuilder.Geometry
// If the triangle has no area, there can never be a point inside // If the triangle has no area, there can never be a point inside
if(TriangleHasArea(t)) if(TriangleHasArea(t))
{ {
float lineside01 = Line2D.GetSideOfLine(t[0].Position, t[1].Position, p.Value.Position); //mxd
float lineside12 = Line2D.GetSideOfLine(t[1].Position, t[2].Position, p.Value.Position); Vector2D pos0 = t[0].Position;
float lineside20 = Line2D.GetSideOfLine(t[2].Position, t[0].Position, p.Value.Position); Vector2D pos1 = t[1].Position;
Vector2D pos2 = t[2].Position;
float lineside01 = Line2D.GetSideOfLine(pos0, pos1, p.Value.Position);
float lineside12 = Line2D.GetSideOfLine(pos1, pos2, p.Value.Position);
float lineside20 = Line2D.GetSideOfLine(pos2, pos0, p.Value.Position);
float u_on_line = 0.5f; float u_on_line = 0.5f;
// If point p is on the line of an edge, find out where on the edge segment p is. // If point p is on the line of an edge, find out where on the edge segment p is.
if(lineside01 == 0.0f) if(lineside01 == 0.0f)
u_on_line = Line2D.GetNearestOnLine(t[0].Position, t[1].Position, p.Value.Position); u_on_line = Line2D.GetNearestOnLine(pos0, pos1, p.Value.Position);
else if(lineside12 == 0.0f) else if(lineside12 == 0.0f)
u_on_line = Line2D.GetNearestOnLine(t[1].Position, t[2].Position, p.Value.Position); u_on_line = Line2D.GetNearestOnLine(pos1, pos2, p.Value.Position);
else if(lineside20 == 0.0f) else if(lineside20 == 0.0f)
u_on_line = Line2D.GetNearestOnLine(t[2].Position, t[0].Position, p.Value.Position); u_on_line = Line2D.GetNearestOnLine(pos2, pos0, p.Value.Position);
// If any of the lineside results are 0 then that means the point p lies on that edge and we // If any of the lineside results are 0 then that means the point p lies on that edge and we
// need to test if the lines adjacent to the point p are in the triangle or not. // need to test if the lines adjacent to the point p are in the triangle or not.
@ -877,9 +888,10 @@ namespace CodeImp.DoomBuilder.Geometry
// Line is inside triangle, because p2 is // Line is inside triangle, because p2 is
return true; return true;
} }
// Test if p2 is on an edge of the triangle and if it is we would // Test if p2 is on an edge of the triangle and if it is we would
// like to know where on the edge segment p2 is // like to know where on the edge segment p2 is
else if(s01 == 0.0f) if(s01 == 0.0f)
{ {
p2_on_edge = Line2D.GetNearestOnLine(t[0].Position, t[1].Position, p2); p2_on_edge = Line2D.GetNearestOnLine(t[0].Position, t[1].Position, p2);
p1_on_same_edge = Line2D.GetSideOfLine(t[0].Position, t[1].Position, p1); p1_on_same_edge = Line2D.GetSideOfLine(t[0].Position, t[1].Position, p1);
@ -912,13 +924,10 @@ namespace CodeImp.DoomBuilder.Geometry
Line2D t20 = new Line2D(t[2].Position, t[0].Position); Line2D t20 = new Line2D(t[2].Position, t[0].Position);
float pu, pt; float pu, pt;
// Test intersections //mxd. Test intersections
t01.GetIntersection(p, out pu, out pt); if(t01.GetIntersection(p, out pu, out pt)) return true;
if(!float.IsNaN(pu) && (pu >= 0.0f) && (pu <= 1.0f) && (pt >= 0.0f) && (pt <= 1.0f)) return true; if(t12.GetIntersection(p, out pu, out pt)) return true;
t12.GetIntersection(p, out pu, out pt); if(t20.GetIntersection(p, out pu, out pt)) return true;
if(!float.IsNaN(pu) && (pu >= 0.0f) && (pu <= 1.0f) && (pt >= 0.0f) && (pt <= 1.0f)) return true;
t20.GetIntersection(p, out pu, out pt);
if(!float.IsNaN(pu) && (pu >= 0.0f) && (pu <= 1.0f) && (pt >= 0.0f) && (pt <= 1.0f)) return true;
return false; return false;
} }
@ -926,24 +935,33 @@ namespace CodeImp.DoomBuilder.Geometry
// This checks if the triangle has an area greater than 0 // This checks if the triangle has an area greater than 0
private static bool TriangleHasArea(EarClipVertex[] t) private static bool TriangleHasArea(EarClipVertex[] t)
{ {
return ((t[0].Position.x * (t[1].Position.y - t[2].Position.y) + Vector2D tp0 = t[0].Position;
t[1].Position.x * (t[2].Position.y - t[0].Position.y) + Vector2D tp1 = t[1].Position;
t[2].Position.x * (t[0].Position.y - t[1].Position.y)) != 0.0f); Vector2D tp2 = t[2].Position;
return ((tp0.x * (tp1.y - tp2.y) +
tp1.x * (tp2.y - tp0.y) +
tp2.x * (tp0.y - tp1.y)) != 0.0f);
} }
// This adds an array of vertices // This adds an array of vertices
private static void AddTriangleToList(EarClipVertex[] triangle, List<Vector2D> verticeslist, List<Sidedef> sidedefslist, bool last) private static void AddTriangleToList(EarClipVertex[] triangle, List<Vector2D> verticeslist, List<Sidedef> sidedefslist, bool last)
{ {
//mxd
EarClipVertex v0 = triangle[0];
EarClipVertex v1 = triangle[1];
EarClipVertex v2 = triangle[2];
// Create triangle // Create triangle
verticeslist.Add(triangle[0].Position); verticeslist.Add(v0.Position);
sidedefslist.Add(triangle[0].Sidedef); sidedefslist.Add(v0.Sidedef);
verticeslist.Add(triangle[1].Position); verticeslist.Add(v1.Position);
sidedefslist.Add(triangle[1].Sidedef); sidedefslist.Add(v1.Sidedef);
verticeslist.Add(triangle[2].Position); verticeslist.Add(v2.Position);
if(!last) sidedefslist.Add(null); else sidedefslist.Add(triangle[2].Sidedef); sidedefslist.Add(!last ? null : v2.Sidedef);
// Modify the first earclipvertex of this triangle, it no longer lies along a sidedef // Modify the first earclipvertex of this triangle, it no longer lies along a sidedef
triangle[0].Sidedef = null; v0.Sidedef = null;
} }
#endregion #endregion

View file

@ -546,6 +546,14 @@ namespace CodeImp.DoomBuilder.BuilderModes
pos.y > General.Map.Config.TopBoundary || pos.y < General.Map.Config.BottomBoundary) pos.y > General.Map.Config.TopBoundary || pos.y < General.Map.Config.BottomBoundary)
return false; return false;
//mxd. Avoid zero-length lines...
if(points.Count > 0)
{
Vector2D delta = points[points.Count - 1].pos - pos;
if((Math.Abs(delta.x) <= 0.001f) && (Math.Abs(delta.y) <= 0.001f))
return true;
}
DrawnVertex newpoint = new DrawnVertex(); DrawnVertex newpoint = new DrawnVertex();
newpoint.pos = pos; newpoint.pos = pos;
newpoint.stitch = stitch; newpoint.stitch = stitch;

View file

@ -60,6 +60,12 @@ namespace CodeImp.DoomBuilder.BuilderModes
private bool floorchanged; private bool floorchanged;
private bool ceilingchanged; private bool ceilingchanged;
//mxd. Absolute lights are not affected by brightness transfers...
private bool lightfloorabsolute;
private bool lightceilingabsolute;
private int lightfloor;
private int lightceiling;
#endregion #endregion
#region ================== Properties #region ================== Properties
@ -299,18 +305,17 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Fetch ZDoom fields // Fetch ZDoom fields
int color = sector.Fields.GetValue("lightcolor", -1); int color = sector.Fields.GetValue("lightcolor", -1);
int flight = sector.Fields.GetValue("lightfloor", 0); lightfloor = sector.Fields.GetValue("lightfloor", 0);
bool fabs = sector.Fields.GetValue("lightfloorabsolute", false); lightfloorabsolute = sector.Fields.GetValue("lightfloorabsolute", false);
int clight = sector.Fields.GetValue("lightceiling", 0); lightceiling = sector.Fields.GetValue("lightceiling", 0);
bool cabs = sector.Fields.GetValue("lightceilingabsolute", false); lightceilingabsolute = sector.Fields.GetValue("lightceilingabsolute", false);
//int alpha = sector.Fields.GetValue("lightalpha", 255);
// Determine colors & light levels // Determine colors & light levels
PixelColor lightcolor = PixelColor.FromInt(color); PixelColor lightcolor = PixelColor.FromInt(color);
if(!fabs) flight = sector.Brightness + flight; if(!lightfloorabsolute) lightfloor = sector.Brightness + lightfloor;
if(!cabs) clight = sector.Brightness + clight; if(!lightceilingabsolute) lightceiling = sector.Brightness + lightceiling;
PixelColor floorbrightness = PixelColor.FromInt(mode.CalculateBrightness(flight)); PixelColor floorbrightness = PixelColor.FromInt(mode.CalculateBrightness(lightfloor));
PixelColor ceilingbrightness = PixelColor.FromInt(mode.CalculateBrightness(clight)); PixelColor ceilingbrightness = PixelColor.FromInt(mode.CalculateBrightness(lightceiling));
PixelColor floorcolor = PixelColor.Modulate(lightcolor, floorbrightness); PixelColor floorcolor = PixelColor.Modulate(lightcolor, floorbrightness);
PixelColor ceilingcolor = PixelColor.Modulate(lightcolor, ceilingbrightness); PixelColor ceilingcolor = PixelColor.Modulate(lightcolor, ceilingbrightness);
floor.color = floorcolor.WithAlpha(255).ToInt(); floor.color = floorcolor.WithAlpha(255).ToInt();
@ -369,7 +374,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
{ {
lightlevels[lightlevels.Count - 1].colorbelow = stored.colorbelow; lightlevels[lightlevels.Count - 1].colorbelow = stored.colorbelow;
lightlevels[lightlevels.Count - 1].brightnessbelow = stored.brightnessbelow; lightlevels[lightlevels.Count - 1].brightnessbelow = stored.brightnessbelow;
lightlevels[lightlevels.Count - 1].color = GetLevelColor(stored); lightlevels[lightlevels.Count - 1].color = GetLevelColor(stored, lightlevels[lightlevels.Count - 1]);
} }
//mxd. Cast light properties from top to bottom //mxd. Cast light properties from top to bottom
@ -390,12 +395,12 @@ namespace CodeImp.DoomBuilder.BuilderModes
{ {
l.colorbelow = stored.colorbelow; l.colorbelow = stored.colorbelow;
l.brightnessbelow = stored.brightnessbelow; l.brightnessbelow = stored.brightnessbelow;
l.color = GetLevelColor(stored); l.color = GetLevelColor(stored, l);
} }
else if(l.restrictlighting) else if(l.restrictlighting)
{ {
if(!pl.restrictlighting && pl != ceiling) stored = pl; if(!pl.restrictlighting && pl != ceiling) stored = pl;
l.color = GetLevelColor(stored); l.color = GetLevelColor(stored, l);
// This is the bottom side of extrafloor with "restrict lighting" flag. Make it cast stored light props. // This is the bottom side of extrafloor with "restrict lighting" flag. Make it cast stored light props.
if(l.type == SectorLevelType.Ceiling) if(l.type == SectorLevelType.Ceiling)
@ -406,10 +411,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Use light and color settings from previous layer // Use light and color settings from previous layer
l.colorbelow = pl.colorbelow; l.colorbelow = pl.colorbelow;
l.brightnessbelow = pl.brightnessbelow; l.brightnessbelow = pl.brightnessbelow;
l.color = GetLevelColor(pl); l.color = GetLevelColor(pl, l);
// Also colorize previous layer using next higher level color // Also colorize previous layer using next higher level color
if(i + 2 < lightlevels.Count) pl.color = GetLevelColor(lightlevels[i + 2]); if(i + 2 < lightlevels.Count) pl.color = GetLevelColor(lightlevels[i + 2], pl);
} }
else else
{ {
@ -452,7 +457,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
if(src.colorbelow.a > 0 && src.brightnessbelow != -1) if(src.colorbelow.a > 0 && src.brightnessbelow != -1)
{ {
// Only surface brightness is retained when a glowing flat is used as extrafloor texture // Only surface brightness is retained when a glowing flat is used as extrafloor texture
if(!l.affectedbyglow) l.color = GetLevelColor(src); if(!l.affectedbyglow) l.color = GetLevelColor(src, l);
// Transfer brightnessbelow and colorbelow if current level is not extrafloor top // Transfer brightnessbelow and colorbelow if current level is not extrafloor top
if(!(l.extrafloor && l.type == SectorLevelType.Floor)) if(!(l.extrafloor && l.type == SectorLevelType.Floor))
@ -604,9 +609,16 @@ namespace CodeImp.DoomBuilder.BuilderModes
} }
//mxd //mxd
private int GetLevelColor(SectorLevel src) private int GetLevelColor(SectorLevel src, SectorLevel target)
{ {
PixelColor brightness = PixelColor.FromInt(mode.CalculateBrightness(src.brightnessbelow)); PixelColor brightness;
if(lightfloorabsolute && target == floor)
brightness = PixelColor.FromInt(mode.CalculateBrightness(lightfloor));
else if(lightceilingabsolute && target == ceiling)
brightness = PixelColor.FromInt(mode.CalculateBrightness(lightceiling));
else
brightness = PixelColor.FromInt(mode.CalculateBrightness(src.brightnessbelow));
PixelColor color = PixelColor.Modulate(src.colorbelow, brightness); PixelColor color = PixelColor.Modulate(src.colorbelow, brightness);
return color.WithAlpha(255).ToInt(); return color.WithAlpha(255).ToInt();
} }