mirror of
https://git.do.srb2.org/STJr/UltimateZoneBuilder.git
synced 2024-11-23 12:22:35 +00:00
working on visual mode
This commit is contained in:
parent
e0539e626b
commit
1336103adc
6 changed files with 212 additions and 8 deletions
|
@ -112,5 +112,32 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
|||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Methods
|
||||
|
||||
// TEST:
|
||||
public override void OnMouseDown(MouseEventArgs e)
|
||||
{
|
||||
// Make ray
|
||||
Vector3D start = CameraPosition;
|
||||
Vector3D delta = CameraTarget.GetFixedLength(General.Settings.ViewDistance);
|
||||
VisualPickResult pick = PickObject(start, start + delta);
|
||||
|
||||
// Any result?
|
||||
if(pick.geometry != null)
|
||||
{
|
||||
if(pick.geometry is VisualMiddleSingle)
|
||||
{
|
||||
VisualMiddleSingle sd = (pick.geometry as VisualMiddleSingle);
|
||||
General.Interface.ShowLinedefInfo(sd.Sidedef.Line);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
General.Interface.HideInfo();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,6 +47,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
|||
|
||||
#region ================== Variables
|
||||
|
||||
private float top;
|
||||
private float bottom;
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Properties
|
||||
|
@ -136,6 +139,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
|||
verts[4] = verts[2];
|
||||
verts[5] = new WorldVertex(v2.x, v2.y, geobottom, pc.ToInt(), t2.x, t2.y);
|
||||
|
||||
// Keep properties
|
||||
this.top = geotop;
|
||||
this.bottom = geobottom;
|
||||
|
||||
// Apply vertices
|
||||
base.SetVertices(verts);
|
||||
return true;
|
||||
|
@ -151,6 +158,21 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
|||
|
||||
#region ================== Methods
|
||||
|
||||
// This performs a fast test in object picking
|
||||
public override bool PickFastReject(Vector3D from, Vector3D to, Vector3D dir)
|
||||
{
|
||||
// We can't do any faster than the accurate pick
|
||||
return true;
|
||||
}
|
||||
|
||||
// This performs an accurate test for object picking
|
||||
public override bool PickAccurate(Vector3D from, Vector3D to, Vector3D dir, ref float u_ray)
|
||||
{
|
||||
// Check if point is between top and bottom
|
||||
u_ray = PickRayU;
|
||||
return (PickIntersect.z >= bottom) && (PickIntersect.z <= top);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,6 +70,11 @@ namespace CodeImp.DoomBuilder.VisualModes
|
|||
internal int Triangles { get { return triangles; } }
|
||||
internal int RenderPassInt { get { return renderpass; } }
|
||||
|
||||
// These are only here so that we can call this on all geometry
|
||||
// but it is only implemented in the VisualSidedef class
|
||||
internal Vector3D PickIntersect { set { } }
|
||||
internal float PickRayU { set { } }
|
||||
|
||||
/// <summary>
|
||||
/// Render pass in which this geometry must be rendered. Default is Solid.
|
||||
/// </summary>
|
||||
|
@ -110,13 +115,31 @@ namespace CodeImp.DoomBuilder.VisualModes
|
|||
if(sector != null) sector.NeedsUpdateGeo = true;
|
||||
}
|
||||
|
||||
// This compares for sorting
|
||||
// This compares for sorting by sector
|
||||
public int CompareTo(VisualGeometry other)
|
||||
{
|
||||
// Compare sectors
|
||||
return this.sector.Sector.Index - other.sector.Sector.Index;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is called when the geometry must be tested for line intersection. This should reject
|
||||
/// as fast as possible to rule out all geometry that certainly does not touch the line.
|
||||
/// </summary>
|
||||
public virtual bool PickFastReject(Vector3D from, Vector3D to, Vector3D dir)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is called when the geometry must be tested for line intersection. This should perform
|
||||
/// accurate hit detection and set u_ray to the position on the ray where this hits the geometry.
|
||||
/// </summary>
|
||||
public virtual bool PickAccurate(Vector3D from, Vector3D to, Vector3D dir, ref float u_ray)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -301,12 +301,12 @@ namespace CodeImp.DoomBuilder.VisualModes
|
|||
if(ld.SideOfLine(campos2d) < 0)
|
||||
{
|
||||
// Do front of line
|
||||
if(ld.Front != null) ProcessSidedef(ld.Front);
|
||||
if(ld.Front != null) ProcessSidedefCulling(ld.Front);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Do back of line
|
||||
if(ld.Back != null) ProcessSidedef(ld.Back);
|
||||
if(ld.Back != null) ProcessSidedefCulling(ld.Back);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -336,7 +336,7 @@ namespace CodeImp.DoomBuilder.VisualModes
|
|||
float side = sd.Line.SideOfLine(campos2d);
|
||||
if(((side < 0) && sd.IsFront) ||
|
||||
((side > 0) && !sd.IsFront))
|
||||
ProcessSidedef(sd);
|
||||
ProcessSidedefCulling(sd);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -354,7 +354,7 @@ namespace CodeImp.DoomBuilder.VisualModes
|
|||
}
|
||||
|
||||
// This finds and adds visible sectors
|
||||
private void ProcessSidedef(Sidedef sd)
|
||||
private void ProcessSidedefCulling(Sidedef sd)
|
||||
{
|
||||
VisualSector vs;
|
||||
|
||||
|
@ -453,16 +453,141 @@ namespace CodeImp.DoomBuilder.VisualModes
|
|||
public VisualPickResult PickObject(Vector3D from, Vector3D to)
|
||||
{
|
||||
VisualPickResult result = new VisualPickResult();
|
||||
Vector2D from2d = from;
|
||||
Vector2D to2d = to;
|
||||
|
||||
// Setup no result
|
||||
result.geometry = null;
|
||||
result.hitpos = new Vector3D();
|
||||
result.u_ray = float.MaxValue;
|
||||
|
||||
// Pick geometry
|
||||
// Find all blocks we are intersecting
|
||||
List<VisualBlockEntry> blocks = blockmap.GetLineBlocks(from, to);
|
||||
|
||||
// TODO
|
||||
// Go for all lines to see which ones we intersect
|
||||
// We will collect geometry from the sectors and sidedefs
|
||||
Line2D ray2d = new Line2D(from2d, to2d);
|
||||
Dictionary<Linedef, Linedef> lines = new Dictionary<Linedef, Linedef>(blocks.Count * 10);
|
||||
Dictionary<Sector, VisualSector> sectors = new Dictionary<Sector, VisualSector>(blocks.Count * 10);
|
||||
List<VisualGeometry> potentialgeometry = new List<VisualGeometry>(blocks.Count * 10);
|
||||
foreach(VisualBlockEntry b in blocks)
|
||||
{
|
||||
foreach(Linedef ld in b.Lines)
|
||||
{
|
||||
// Make sure we don't test a line twice
|
||||
if(!lines.ContainsKey(ld))
|
||||
{
|
||||
lines.Add(ld, ld);
|
||||
|
||||
// Intersecting?
|
||||
float u;
|
||||
if(ld.Line.GetIntersection(ray2d, out u))
|
||||
{
|
||||
// Check on which side we are
|
||||
float side = ld.SideOfLine(from2d);
|
||||
|
||||
// Calculate intersection point
|
||||
Vector3D intersect = from + to * u;
|
||||
|
||||
// We must add the sectors of both sides of the line
|
||||
// If we wouldn't, then aiming at a sector that is just within range
|
||||
// could result in an incorrect hit (because the far line of the
|
||||
// sector may not be included in this loop)
|
||||
if(ld.Front != null)
|
||||
{
|
||||
// Find the visualsector
|
||||
if(allsectors.ContainsKey(ld.Front.Sector))
|
||||
{
|
||||
VisualSector vs = allsectors[ld.Front.Sector];
|
||||
|
||||
// Add sector if not already added
|
||||
if(!sectors.ContainsKey(ld.Front.Sector))
|
||||
{
|
||||
sectors.Add(ld.Front.Sector, vs);
|
||||
potentialgeometry.AddRange(vs.FixedGeometry);
|
||||
}
|
||||
|
||||
// Add sidedef if on the front side
|
||||
if(side < 0.0f)
|
||||
{
|
||||
int previndex = potentialgeometry.Count;
|
||||
potentialgeometry.AddRange(vs.GetSidedefGeometry(ld.Front));
|
||||
for(int i = previndex; i < potentialgeometry.Count; i++)
|
||||
{
|
||||
potentialgeometry[i].PickIntersect = intersect;
|
||||
potentialgeometry[i].PickRayU = u;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add back side also
|
||||
if(ld.Back != null)
|
||||
{
|
||||
// Find the visualsector
|
||||
if(allsectors.ContainsKey(ld.Back.Sector))
|
||||
{
|
||||
VisualSector vs = allsectors[ld.Back.Sector];
|
||||
|
||||
// Add sector if not already added
|
||||
if(!sectors.ContainsKey(ld.Back.Sector))
|
||||
{
|
||||
sectors.Add(ld.Back.Sector, vs);
|
||||
potentialgeometry.AddRange(vs.FixedGeometry);
|
||||
}
|
||||
|
||||
// Add sidedef if on the front side
|
||||
if(side > 0.0f)
|
||||
{
|
||||
int previndex = potentialgeometry.Count;
|
||||
potentialgeometry.AddRange(vs.GetSidedefGeometry(ld.Back));
|
||||
for(int i = previndex; i < potentialgeometry.Count; i++)
|
||||
{
|
||||
potentialgeometry[i].PickIntersect = intersect;
|
||||
potentialgeometry[i].PickRayU = u;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now we have a list of potential geometry that lies along the trace line.
|
||||
// We still don't know what geometry actually hits, but we ruled out that which doesn't get even close.
|
||||
// This is still too much for accurate intersection testing, so we do a fast reject pass first.
|
||||
Vector3D direction = to - from;
|
||||
direction = direction.GetNormal();
|
||||
List<VisualGeometry> likelygeometry = new List<VisualGeometry>(potentialgeometry.Count);
|
||||
foreach(VisualGeometry g in potentialgeometry)
|
||||
{
|
||||
if(g.PickFastReject(from, to, direction)) likelygeometry.Add(g);
|
||||
}
|
||||
|
||||
// Now we do an accurate intersection test for all resulting geometry
|
||||
// We keep only the closest hit!
|
||||
foreach(VisualGeometry g in likelygeometry)
|
||||
{
|
||||
float u = result.u_ray;
|
||||
if(g.PickAccurate(from, to, direction, ref u))
|
||||
{
|
||||
// Closer than previous find?
|
||||
if(u < result.u_ray)
|
||||
{
|
||||
result.u_ray = u;
|
||||
result.geometry = g;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Setup final result
|
||||
result.hitpos = from + to * result.u_ray;
|
||||
|
||||
// Done
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Rendering
|
||||
|
|
|
@ -42,6 +42,7 @@ namespace CodeImp.DoomBuilder.VisualModes
|
|||
{
|
||||
// Members
|
||||
public VisualGeometry geometry;
|
||||
public float u_ray;
|
||||
public Vector3D hitpos;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,11 +51,17 @@ namespace CodeImp.DoomBuilder.VisualModes
|
|||
// Original sidedef
|
||||
private Sidedef sidedef;
|
||||
|
||||
// Intersection point for current pick test
|
||||
private Vector3D pickintersect;
|
||||
private float pickrayu;
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Properties
|
||||
|
||||
public Sidedef Sidedef { get { return sidedef; } }
|
||||
new public Vector3D PickIntersect { get { return pickintersect; } internal set { pickintersect = value; } }
|
||||
new public float PickRayU { get { return pickrayu; } internal set { pickrayu = value; } }
|
||||
|
||||
#endregion
|
||||
|
||||
|
|
Loading…
Reference in a new issue