Пример #1
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);
        }
Пример #2
0
 /// <summary>
 /// This creates visual geometry that is bound to a sidedef. This geometry is only visible when the sidedef is visible. It is automatically back-face culled during rendering and automatically XY intersection tested as well as back-face culled during object picking.
 /// </summary>
 /// <param name="vs"></param>
 /// <param name="sd"></param>
 public VisualGeometry(VisualSector vs, Sidedef sd)
 {
     this.sector        = vs;
     this.sidedef       = sd;
     this.ModulateColor = new PixelColor(255, 255, 255, 255);
 }
Пример #3
0
 /// <summary>
 /// This creates visual geometry that is bound to a sidedef. This geometry is only visible when the sidedef is visible. It is automatically back-face culled during rendering and automatically XY intersection tested as well as back-face culled during object picking.
 /// </summary>
 protected VisualGeometry(VisualSector vs, Sidedef sd)
 {
     this.sector       = vs;
     this.sidedef      = sd;
     this.geometrytype = VisualGeometryType.UNKNOWN;             //mxd
 }
Пример #4
0
 /// <summary>
 /// This creates sector-global visual geometry. This geometry is always visible when any of the sector is visible.
 /// </summary>
 public VisualGeometry(VisualSector vs)
 {
     this.sector        = vs;
     this.ModulateColor = new PixelColor(255, 255, 255, 255);
 }
Пример #5
0
 /// <summary>
 /// This creates sector-global visual geometry. This geometry is always visible when any of the sector is visible.
 /// </summary>
 protected VisualGeometry(VisualSector vs)
 {
     this.sector       = vs;
     this.geometrytype = VisualGeometryType.UNKNOWN;             //mxd
 }