Changed drawing behavior so that drawn lines are not corrected to clockwise orientation

This commit is contained in:
codeimp 2009-05-06 14:50:17 +00:00
parent 65521d1ea6
commit 91b76bcb5b
5 changed files with 92 additions and 44 deletions

View file

@ -76,6 +76,27 @@ namespace CodeImp.DoomBuilder.Geometry
foreach(EarClipVertex v in p) base.AddLast(v); foreach(EarClipVertex v in p) base.AddLast(v);
} }
// This calculates the area
public float CalculateArea()
{
// Multiply the x coordinate of each vertex by the y coordinate of the next vertex.
// Multiply the y coordinate of each vertex by the x coordinate of the next vertex.
// Subtract these.
float result = 0.0f;
int firstcalculated = 0;
LinkedListNode<EarClipVertex> n1 = base.First;
while(firstcalculated < 2)
{
LinkedListNode<EarClipVertex> n2 = n1.Next ?? base.First;
float a = n1.Value.Position.x * n2.Value.Position.y;
float b = n1.Value.Position.y * n2.Value.Position.x;
result += a - b;
n1 = n2;
if(n2 == base.First) firstcalculated++;
}
return Math.Abs(result / 2.0f);
}
// This creates a bounding box from the outer polygon // This creates a bounding box from the outer polygon
public RectangleF CreateBBox() public RectangleF CreateBBox()
{ {

View file

@ -827,6 +827,7 @@ namespace CodeImp.DoomBuilder.Geometry
List<Vertex> newverts = new List<Vertex>(); List<Vertex> newverts = new List<Vertex>();
List<Vertex> intersectverts = new List<Vertex>(); List<Vertex> intersectverts = new List<Vertex>();
List<Linedef> newlines = new List<Linedef>(); List<Linedef> newlines = new List<Linedef>();
List<bool> newlinescw = new List<bool>();
List<Linedef> oldlines = new List<Linedef>(General.Map.Map.Linedefs); List<Linedef> oldlines = new List<Linedef>(General.Map.Map.Linedefs);
List<Sidedef> insidesides = new List<Sidedef>(); List<Sidedef> insidesides = new List<Sidedef>();
List<Vertex> mergeverts = new List<Vertex>(); List<Vertex> mergeverts = new List<Vertex>();
@ -839,7 +840,7 @@ namespace CodeImp.DoomBuilder.Geometry
if(points.Count > 0) if(points.Count > 0)
{ {
/***************************************************\ /***************************************************\
STEP 1: Create the new geometry Create the drawing
\***************************************************/ \***************************************************/
// Make first vertex // Make first vertex
@ -923,6 +924,10 @@ namespace CodeImp.DoomBuilder.Geometry
// Join merge vertices so that overlapping vertices in the draw become one. // Join merge vertices so that overlapping vertices in the draw become one.
MapSet.JoinVertices(mergeverts, mergeverts, false, MapSet.STITCH_DISTANCE); MapSet.JoinVertices(mergeverts, mergeverts, false, MapSet.STITCH_DISTANCE);
/***************************************************\
Find a way to close the drawing
\***************************************************/
// We prefer a closed polygon, because then we can determine the interior properly // We prefer a closed polygon, because then we can determine the interior properly
// Check if the two ends of the polygon are closed // Check if the two ends of the polygon are closed
bool drawingclosed = false; bool drawingclosed = false;
@ -1089,14 +1094,13 @@ namespace CodeImp.DoomBuilder.Geometry
MapSet.SplitLinesByVertices(newlines, mergeverts, MapSet.STITCH_DISTANCE, null); MapSet.SplitLinesByVertices(newlines, mergeverts, MapSet.STITCH_DISTANCE, null);
/***************************************************\ /***************************************************\
STEP 2: Merge the new geometry Determine drawing interior
\***************************************************/ \***************************************************/
// In step 3 we will make sectors on the front sides and join sectors on the // In step 3 we will make sectors on the interior sides and join sectors on the
// back sides, but because the user could have drawn counterclockwise or just // exterior sides, but because the user could have drawn counterclockwise or just
// some weird polygon this could result in problems. The following code adjusts // some weird polygon. The following code figures out the interior side of all
// the direction of all new lines so that their front (right) side is facing // new lines.
// the interior of the new drawn polygon.
map.Update(true, false); map.Update(true, false);
foreach(Linedef ld in newlines) foreach(Linedef ld in newlines)
{ {
@ -1109,7 +1113,7 @@ namespace CodeImp.DoomBuilder.Geometry
EarClipPolygon pathpoly = tracepath.MakePolygon(true); EarClipPolygon pathpoly = tracepath.MakePolygon(true);
// Check if the front of the line is outside the polygon // Check if the front of the line is outside the polygon
if(!pathpoly.Intersect(ld.GetSidePoint(true))) if((pathpoly.CalculateArea() > 0.001f) && !pathpoly.Intersect(ld.GetSidePoint(true)))
{ {
// Now trace from the back side of the line to see if // Now trace from the back side of the line to see if
// the back side lies in the interior. I don't want to // the back side lies in the interior. I don't want to
@ -1123,19 +1127,29 @@ namespace CodeImp.DoomBuilder.Geometry
tracepath = new LinedefTracePath(pathlines); tracepath = new LinedefTracePath(pathlines);
pathpoly = tracepath.MakePolygon(true); pathpoly = tracepath.MakePolygon(true);
// Check if the back of the line is inside the polygon // Check if the front of the line is inside the polygon
if(pathpoly.Intersect(ld.GetSidePoint(false))) ld.FrontInterior = (pathpoly.CalculateArea() < 0.001f) || pathpoly.Intersect(ld.GetSidePoint(true));
{ }
// We must flip this linedef to face the interior else
ld.FlipVertices(); {
ld.FlipSidedefs(); ld.FrontInterior = true;
ld.UpdateCache();
}
} }
} }
else
{
ld.FrontInterior = true;
}
}
else
{
ld.FrontInterior = true;
} }
} }
/***************************************************\
Merge the new geometry
\***************************************************/
// Mark only the vertices that should be merged // Mark only the vertices that should be merged
map.ClearMarkedVertices(false); map.ClearMarkedVertices(false);
foreach(Vertex v in mergeverts) v.Marked = true; foreach(Vertex v in mergeverts) v.Marked = true;
@ -1157,11 +1171,11 @@ namespace CodeImp.DoomBuilder.Geometry
if(!ld.IsDisposed) oldlines.Add(ld); if(!ld.IsDisposed) oldlines.Add(ld);
/***************************************************\ /***************************************************\
STEP 3: Join and create new sectors Join and create new sectors
\***************************************************/ \***************************************************/
// The code below atempts to create sectors on the front sides of the drawn // The code below atempts to create sectors on the interior sides of the drawn
// geometry and joins sectors on the back sides of the drawn geometry. // geometry and joins sectors on the other sides of the drawn geometry.
// This code does not change any geometry, it only makes/updates sidedefs. // This code does not change any geometry, it only makes/updates sidedefs.
bool sidescreated = false; bool sidescreated = false;
bool[] frontsdone = new bool[newlines.Count]; bool[] frontsdone = new bool[newlines.Count];
@ -1170,11 +1184,11 @@ namespace CodeImp.DoomBuilder.Geometry
{ {
Linedef ld = newlines[i]; Linedef ld = newlines[i];
// Front not marked as done? // Interior not done yet?
if(!frontsdone[i]) if((ld.FrontInterior && !frontsdone[i]) || (!ld.FrontInterior && !backsdone[i]))
{ {
// Find a way to create a sector here // Find a way to create a sector here
List<LinedefSide> sectorlines = Tools.FindPotentialSectorAt(ld, true); List<LinedefSide> sectorlines = Tools.FindPotentialSectorAt(ld, ld.FrontInterior);
if(sectorlines != null) if(sectorlines != null)
{ {
sidescreated = true; sidescreated = true;
@ -1216,15 +1230,14 @@ namespace CodeImp.DoomBuilder.Geometry
} }
} }
// Back not marked as done? // Exterior not done yet?
if(!backsdone[i]) if((ld.FrontInterior && !backsdone[i]) || (!ld.FrontInterior && !frontsdone[i]))
{ {
// Find a way to create a sector here // Find a way to create a sector here
List<LinedefSide> sectorlines = Tools.FindPotentialSectorAt(ld, false); List<LinedefSide> sectorlines = Tools.FindPotentialSectorAt(ld, !ld.FrontInterior);
if(sectorlines != null) if(sectorlines != null)
{ {
// We don't always want to create a new sector on the back sides // Check if any of the surrounding lines originally have sidedefs we can join
// So first check if any of the surrounding lines originally have sidedefs
Sidedef joinsidedef = null; Sidedef joinsidedef = null;
foreach(LinedefSide ls in sectorlines) foreach(LinedefSide ls in sectorlines)
{ {
@ -1267,6 +1280,10 @@ namespace CodeImp.DoomBuilder.Geometry
} }
} }
/***************************************************\
Corrections and clean up
\***************************************************/
// Make corrections for backward linedefs // Make corrections for backward linedefs
MapSet.FlipBackwardLinedefs(newlines); MapSet.FlipBackwardLinedefs(newlines);

View file

@ -75,6 +75,7 @@ namespace CodeImp.DoomBuilder.Map
private int activate; private int activate;
private int tag; private int tag;
private int[] args; private int[] args;
private bool frontinterior; // for drawing only
// Clone // Clone
private int serializedindex; private int serializedindex;
@ -101,6 +102,7 @@ namespace CodeImp.DoomBuilder.Map
public RectangleF Rect { get { return rect; } } public RectangleF Rect { get { return rect; } }
public int[] Args { get { return args; } } public int[] Args { get { return args; } }
internal int SerializedIndex { get { return serializedindex; } set { serializedindex = value; } } internal int SerializedIndex { get { return serializedindex; } set { serializedindex = value; } }
internal bool FrontInterior { get { return frontinterior; } set { frontinterior = value; } }
#endregion #endregion
@ -489,6 +491,9 @@ namespace CodeImp.DoomBuilder.Map
startvertexlistitem = endvertexlistitem; startvertexlistitem = endvertexlistitem;
endvertexlistitem = vn; endvertexlistitem = vn;
// For drawing, the interior now lies on the other side
frontinterior = !frontinterior;
// Update required (angle changed) // Update required (angle changed)
NeedUpdate(); NeedUpdate();
General.Map.IsChanged = true; General.Map.IsChanged = true;

View file

@ -1886,22 +1886,24 @@ namespace CodeImp.DoomBuilder.Map
// Not the same line? // Not the same line?
if(l1 != l2) if(l1 != l2)
{ {
bool flipresult = (l1.End == l2.Start); bool oppositedirection = (l1.End == l2.Start);
// Merge these two linedefs // Merge these two linedefs
//while(lines.Remove(l1));
//l1.Join(l2);
while(lines.Remove(l2)) ; while(lines.Remove(l2)) ;
l2.Join(l1); l2.Join(l1);
// The flipping is purely a cosmetic to preserve orientation // The flipping is purely a cosmetic to preserve orientation
// when drawing new lines over older lines // when drawing new lines over older lines
if(flipresult) if(oppositedirection)
{ {
l1.FlipVertices(); l1.FlipVertices();
l1.FlipSidedefs(); l1.FlipSidedefs();
} }
// Direction is now the same, so the interior side is also the same
// We have to copy the interior side to preserve this for drawing
l1.FrontInterior = l2.FrontInterior;
joinsdone++; joinsdone++;
joined = true; joined = true;
break; break;
@ -1922,22 +1924,24 @@ namespace CodeImp.DoomBuilder.Map
// Not the same line? // Not the same line?
if(l1 != l2) if(l1 != l2)
{ {
bool flipresult = (l1.End == l2.Start); bool oppositedirection = (l1.Start == l2.End);
// Merge these two linedefs // Merge these two linedefs
//while(lines.Remove(l1));
//l1.Join(l2);
while(lines.Remove(l2)) ; while(lines.Remove(l2)) ;
l2.Join(l1); l2.Join(l1);
// The flipping is purely a cosmetic to preserve orientation // The flipping is purely a cosmetic to preserve orientation
// when drawing new lines over older lines // when drawing new lines over older lines
if(flipresult) if(oppositedirection)
{ {
l1.FlipVertices(); l1.FlipVertices();
l1.FlipSidedefs(); l1.FlipSidedefs();
} }
// Direction is now the same, so the interior side is also the same
// We have to copy the interior side to preserve this for drawing
l1.FrontInterior = l2.FrontInterior;
joinsdone++; joinsdone++;
joined = true; joined = true;
break; break;

View file

@ -291,6 +291,14 @@ namespace CodeImp.DoomBuilder.Map
// This removes textures that are not required // This removes textures that are not required
public void RemoveUnneededTextures(bool removemiddle, bool force) public void RemoveUnneededTextures(bool removemiddle, bool force)
{ {
// The middle texture can be removed regardless of any sector tag or linedef action
if(!MiddleRequired() && removemiddle)
{
this.texnamemid = "-";
this.longtexnamemid = MapSet.EmptyLongName;
General.Map.IsChanged = true;
}
// Check if the line or sectors have no action or tags because // Check if the line or sectors have no action or tags because
// if they do, any texture on this side could be needed // if they do, any texture on this side could be needed
if(((linedef.Tag <= 0) && (linedef.Action == 0) && (sector.Tag <= 0) && if(((linedef.Tag <= 0) && (linedef.Action == 0) && (sector.Tag <= 0) &&
@ -304,13 +312,6 @@ namespace CodeImp.DoomBuilder.Map
General.Map.IsChanged = true; General.Map.IsChanged = true;
} }
if(!MiddleRequired() && removemiddle)
{
this.texnamemid = "-";
this.longtexnamemid = MapSet.EmptyLongName;
General.Map.IsChanged = true;
}
if(!LowRequired()) if(!LowRequired())
{ {
this.texnamelow = "-"; this.texnamelow = "-";