//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);
        }
Exemple #4
0
        // 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);
        }