예제 #1
0
        public Vector2 EstTileAtPosWithScroll(Vector2 pos)
        {
            pos *= new Vector2(FSOEnvironment.DPIScaleFactor);
            var sPos = new Vector3(pos, 0);

            var p1 = State.Device.Viewport.Unproject(sPos, State.Camera.Projection, State.Camera.View, Matrix.Identity);

            sPos.Z = 1;
            var p2  = State.Device.Viewport.Unproject(sPos, State.Camera.Projection, State.Camera.View, Matrix.Identity);
            var dir = p2 - p1;

            dir.Normalize();
            var ray = new Ray(p1, p2 - p1);

            ray.Direction.Normalize();
            ray.Position -= new Vector3(0, (State.Level - 1) * 2.95f * 3, 0);

            var baseBox = new BoundingBox(new Vector3(0, -5000, 0), new Vector3(Blueprint.Width * 3, 5000, Blueprint.Height * 3));

            if (baseBox.Contains(ray.Position) != ContainmentType.Contains)
            {
                //move ray start inside box
                var i = baseBox.Intersects(ray);
                if (i != null)
                {
                    ray.Position += ray.Direction * (i.Value + 0.01f);
                }
            }

            var mx = (int)ray.Position.X / 3;
            var my = (int)ray.Position.Z / 3;

            var px = (ray.Direction.X > 0);
            var py = (ray.Direction.Z > 0);

            int iteration = 0;

            while (mx >= 0 && mx < Blueprint.Width && my >= 0 && my < Blueprint.Width)
            {
                //test triangle 1. (centre of tile down xz, we lean towards positive x)
                var plane = new Plane(
                    new Vector3(mx * 3, Blueprint.GetAltPoint(mx, my) * Blueprint.TerrainFactor * 3, my * 3),
                    new Vector3(mx * 3 + 3, Blueprint.GetAltPoint(mx + 1, my) * Blueprint.TerrainFactor * 3, my * 3),
                    new Vector3(mx * 3 + 3, Blueprint.GetAltPoint(mx + 1, my + 1) * Blueprint.TerrainFactor * 3, my * 3 + 3)
                    );
                var tBounds = new BoundingBox(new Vector3(mx * 3, -5000, my * 3), new Vector3(mx * 3 + 3, 5000, my * 3 + 3));

                var t1 = ray.Intersects(plane);
                var t2 = BoxRC2(ray, 3);
                //var t2 = BoxRC(ray, tBounds);
                if (plane.DotCoordinate(ray.Position) > 0)
                {
                    t1 = 0;
                }
                if (t1 != null && t2 != null && t1.Value < t2.Value)
                {
                    //hit the ground...
                    var tentative = ray.Position + ray.Direction * (t1.Value + 0.00001f);

                    //did it hit the correct side of the triangle?
                    var mySide = ((tentative.X / 3) % 1) - ((tentative.Z / 3) % 1);
                    if (mySide >= 0)
                    {
                        return(new Vector2(tentative.X / 3, tentative.Z / 3));
                    }
                    else
                    {
                        //test the other side (positive z)
                        plane = new Plane(
                            new Vector3(mx * 3, Blueprint.GetAltPoint(mx, my) * Blueprint.TerrainFactor * 3, my * 3),
                            new Vector3(mx * 3, Blueprint.GetAltPoint(mx, my + 1) * Blueprint.TerrainFactor * 3, my * 3 + 3),
                            new Vector3(mx * 3 + 3, Blueprint.GetAltPoint(mx + 1, my + 1) * Blueprint.TerrainFactor * 3, my * 3 + 3)
                            );
                        t1 = ray.Intersects(plane);
                        if (t1 != null && t2 != null && t1.Value < t2.Value)
                        {
                            //hit the other side
                            tentative = ray.Position + ray.Direction * (t1.Value + 0.00001f);
                            return(new Vector2(tentative.X / 3, tentative.Z / 3));
                        }
                    }
                }
                if (t2 == null)
                {
                    break;
                }
                ray.Position += ray.Direction * (t2.Value + 0.00001f);

                mx = (!px) ? ((int)Math.Ceiling(ray.Position.X / 3) - 1) :
                     (int)(ray.Position.X / 3);
                my = (!py) ? ((int)Math.Ceiling(ray.Position.Z / 3) - 1) :
                     (int)(ray.Position.Z / 3);

                if (iteration++ > 1000)
                {
                    break;
                }
            }

            //fall back to base positioning
            var bplane = new Plane(new Vector3(0, 0, 0), new Vector3(Blueprint.Width * 3, 0, 0), new Vector3(0, 0, Blueprint.Height * 3));
            var cast   = ray.Intersects(bplane);

            if (cast != null)
            {
                ray.Position += ray.Direction * (cast.Value + 0.01f);
                return(new Vector2(ray.Position.X / 3, ray.Position.Z / 3));
            }

            return(new Vector2(0, 0));
        }
예제 #2
0
        public Vector2 EstTileAtPosWithScroll(Vector2 pos, sbyte level = -1)
        {
            if (level == -1)
            {
                level = State.Level;
            }
            var ray = State.CameraRayAtScreenPos(pos, level);

            var baseBox = new BoundingBox(new Vector3(0, -5000, 0), new Vector3(Blueprint.Width * 3, 5000, Blueprint.Height * 3));

            if (baseBox.Contains(ray.Position) != ContainmentType.Contains)
            {
                //move ray start inside box
                var i = baseBox.Intersects(ray);
                if (i != null)
                {
                    ray.Position += ray.Direction * (i.Value + 0.01f);
                }
            }

            var mx = (int)ray.Position.X / 3;
            var my = (int)ray.Position.Z / 3;

            var px = (ray.Direction.X > 0);
            var py = (ray.Direction.Z > 0);

            var canProj = Blueprint?.Altitude != null;

            int iteration = 0;

            while (mx >= 0 && mx < Blueprint.Width && my >= 0 && my < Blueprint.Width && canProj)
            {
                //test triangle 1. (centre of tile down xz, we lean towards positive x)
                var plane = new Plane(
                    new Vector3(mx * 3, Blueprint.GetAltPoint(mx, my) * Blueprint.TerrainFactor * 3, my * 3),
                    new Vector3(mx * 3 + 3, Blueprint.GetAltPoint(mx + 1, my) * Blueprint.TerrainFactor * 3, my * 3),
                    new Vector3(mx * 3 + 3, Blueprint.GetAltPoint(mx + 1, my + 1) * Blueprint.TerrainFactor * 3, my * 3 + 3)
                    );
                var tBounds = new BoundingBox(new Vector3(mx * 3, -5000, my * 3), new Vector3(mx * 3 + 3, 5000, my * 3 + 3));

                var t1 = ray.Intersects(plane);
                var t2 = BoxRC2(ray, 3);
                //var t2 = BoxRC(ray, tBounds);
                if (plane.DotCoordinate(ray.Position) > 0)
                {
                    t1 = 0;
                }
                if (t1 != null && t2 != null && t1.Value < t2.Value)
                {
                    //hit the ground...
                    var tentative = ray.Position + ray.Direction * (t1.Value + 0.00001f);

                    //did it hit the correct side of the triangle?
                    var mySide = ((tentative.X / 3) % 1) - ((tentative.Z / 3) % 1);
                    if (mySide >= 0)
                    {
                        return(new Vector2(tentative.X / 3, tentative.Z / 3));
                    }
                    else
                    {
                        //test the other side (positive z)
                        plane = new Plane(
                            new Vector3(mx * 3, Blueprint.GetAltPoint(mx, my) * Blueprint.TerrainFactor * 3, my * 3),
                            new Vector3(mx * 3, Blueprint.GetAltPoint(mx, my + 1) * Blueprint.TerrainFactor * 3, my * 3 + 3),
                            new Vector3(mx * 3 + 3, Blueprint.GetAltPoint(mx + 1, my + 1) * Blueprint.TerrainFactor * 3, my * 3 + 3)
                            );
                        t1 = ray.Intersects(plane);
                        if (t1 != null && t2 != null && t1.Value < t2.Value)
                        {
                            //hit the other side
                            tentative = ray.Position + ray.Direction * (t1.Value + 0.00001f);
                            return(new Vector2(tentative.X / 3, tentative.Z / 3));
                        }
                    }
                }
                if (t2 == null)
                {
                    break;
                }
                ray.Position += ray.Direction * (t2.Value + 0.00001f);

                mx = (!px) ? ((int)Math.Ceiling(ray.Position.X / 3) - 1) :
                     (int)(ray.Position.X / 3);
                my = (!py) ? ((int)Math.Ceiling(ray.Position.Z / 3) - 1) :
                     (int)(ray.Position.Z / 3);

                if (iteration++ > 1000)
                {
                    break;
                }
            }

            //fall back to base positioning
            var bplane = new Plane(new Vector3(0, 0, 0), new Vector3(Blueprint.Width * 3, 0, 0), new Vector3(0, 0, Blueprint.Height * 3));
            var cast   = ray.Intersects(bplane);

            if (cast != null)
            {
                ray.Position += ray.Direction * (cast.Value + 0.01f);
                return(new Vector2(ray.Position.X / 3, ray.Position.Z / 3));
            }

            return(new Vector2(0, 0));
        }