//mxd. public Vector2D GetHitPosition() { Vector3D start = General.Map.VisualCamera.Position; Vector3D delta = General.Map.VisualCamera.Target - General.Map.VisualCamera.Position; delta = delta.GetFixedLength(General.Settings.ViewDistance * 0.98f); VisualPickResult target = PickObject(start, start + delta); if (target.picked == null) { return(new Vector2D(float.NaN, float.NaN)); } // Now find where exactly did we hit VisualGeometry vg = target.picked as VisualGeometry; if (vg != null) { return(GetIntersection(start, start + delta, vg.BoundingBox[0], new Vector3D(vg.Vertices[0].nx, vg.Vertices[0].ny, vg.Vertices[0].nz))); } VisualThing vt = target.picked as VisualThing; if (vt != null) { return(GetIntersection(start, start + delta, vt.CenterV3D, D3DDevice.V3D(vt.Center - vt.PositionV3))); } return(new Vector2D(float.NaN, float.NaN)); }
//mxd public List <VisualThing> GetSelectedVisualThings(bool refreshSelection) { if (refreshSelection || selectedVisualThings == null) { selectedVisualThings = new List <VisualThing>(); foreach (KeyValuePair <Thing, VisualThing> group in allthings) { if (group.Value != null && group.Value.Selected) { selectedVisualThings.Add(group.Value); } } //if nothing is selected - try to get thing from hilighted object if (selectedVisualThings.Count == 0) { Vector3D start = General.Map.VisualCamera.Position; Vector3D delta = General.Map.VisualCamera.Target - General.Map.VisualCamera.Position; delta = delta.GetFixedLength(General.Settings.ViewDistance * 0.98f); VisualPickResult target = PickObject(start, start + delta); //not appropriate way to do this, but... if (target.picked is VisualThing) { selectedVisualThings.Add((VisualThing)target.picked); } } } return(selectedVisualThings); }
//mxd private VisualGeometry GetHilightedSurface() { Vector3D start = General.Map.VisualCamera.Position; Vector3D delta = General.Map.VisualCamera.Target - General.Map.VisualCamera.Position; delta = delta.GetFixedLength(General.Settings.ViewDistance * 0.98f); VisualPickResult target = PickObject(start, start + delta); if (target.picked is VisualGeometry) { VisualGeometry vg = (VisualGeometry)target.picked; if (vg.Sector != null) { return(vg); } } return(null); }
// This picks an object from the scene public VisualPickResult PickObject(Vector3D from, Vector3D to) { VisualPickResult result = new VisualPickResult(); Line2D ray2d = new Line2D(from, to); Vector3D delta = to - from; // Setup no result result.picked = null; result.hitpos = new Vector3D(); result.u_ray = 1.0f; // Find all blocks we are intersecting List <VisualBlockEntry> blocks = blockmap.GetLineBlocks(from, to); // Make collections Dictionary <Linedef, Linedef> lines = new Dictionary <Linedef, Linedef>(blocks.Count * 10); Dictionary <Sector, VisualSector> sectors = new Dictionary <Sector, VisualSector>(blocks.Count * 10); List <IVisualPickable> pickables = new List <IVisualPickable>(blocks.Count * 10); // Add geometry from the camera sector if ((General.Map.VisualCamera.Sector != null) && allsectors.ContainsKey(General.Map.VisualCamera.Sector)) { VisualSector vs = allsectors[General.Map.VisualCamera.Sector]; sectors.Add(General.Map.VisualCamera.Sector, vs); foreach (VisualGeometry g in vs.FixedGeometry) { pickables.Add(g); } } // Go for all lines to see which ones we intersect // We will collect geometry from the sectors and sidedefs 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(ray2d.v1); // Calculate intersection point Vector3D intersect = from + delta * 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); foreach (VisualGeometry g in vs.FixedGeometry) { // Must have content if (g.Triangles > 0) { pickables.Add(g); } } } // Add sidedef if on the front side if (side < 0.0f) { List <VisualGeometry> sidedefgeo = vs.GetSidedefGeometry(ld.Front); foreach (VisualGeometry g in sidedefgeo) { // Must have content if (g.Triangles > 0) { g.SetPickResults(intersect, u); pickables.Add(g); } } } } } // 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); foreach (VisualGeometry g in vs.FixedGeometry) { // Must have content if (g.Triangles > 0) { pickables.Add(g); } } } // Add sidedef if on the front side if (side > 0.0f) { List <VisualGeometry> sidedefgeo = vs.GetSidedefGeometry(ld.Back); foreach (VisualGeometry g in sidedefgeo) { // Must have content if (g.Triangles > 0) { g.SetPickResults(intersect, u); pickables.Add(g); } } } } } } } } } // Add all the visible things foreach (VisualThing vt in visiblethings) { pickables.Add(vt); } // 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 <IVisualPickable> potentialpicks = new List <IVisualPickable>(pickables.Count); foreach (IVisualPickable p in pickables) { if (p.PickFastReject(from, to, direction)) { potentialpicks.Add(p); } } // Now we do an accurate intersection test for all resulting geometry // We keep only the closest hit! foreach (IVisualPickable p in potentialpicks) { float u = result.u_ray; if (p.PickAccurate(from, to, direction, ref u)) { // Closer than previous find? if ((u > 0.0f) && (u < result.u_ray)) { result.u_ray = u; result.picked = p; } } } // Setup final result result.hitpos = from + to * result.u_ray; // Done return(result); }