Beispiel #1
0
        /// <summary>
        /// Performs a 2d physical raycast in world coordinates.
        /// </summary>
        /// <param name="start">The starting point in world coordinates.</param>
        /// <param name="end">The desired end point in world coordinates.</param>
        /// <param name="callback">
        /// The callback that is invoked for each hit on the raycast. Note that the order in which each hit occurs isn't deterministic
        /// and may appear random. Return -1 to ignore the curret shape, 0 to terminate the raycast, data.Fraction to clip the ray for current hit, or 1 to continue.
        /// </param>
        /// <param name="firstHit">Returns the first hit that occurs, i.e. the one with the highest proximity to the starting point.</param>
        /// <returns>Returns whether anything has been hit.</returns>
        public bool RayCast(Vector2 start, Vector2 end, RayCastCallback callback, out RayCastData firstHit)
        {
            if (callback == null)
            {
                callback = RayCast_DefaultCallback;
            }

            Vector2 fsWorldCoordA = PhysicsUnit.LengthToPhysical * start;
            Vector2 fsWorldCoordB = PhysicsUnit.LengthToPhysical * end;

            float       firstHitFraction = float.MaxValue;
            RayCastData firstHitLocal    = default(RayCastData);

            this.native.RayCast(delegate(Fixture fixture, Vector2 pos, Vector2 normal, float fraction)
            {
                RayCastData data = new RayCastData(
                    fixture.UserData as ShapeInfo,
                    PhysicsUnit.LengthToDuality * pos,
                    normal,
                    fraction);

                float result = callback(data);
                if (result >= 0.0f && data.Fraction < firstHitFraction)
                {
                    firstHitLocal    = data;
                    firstHitFraction = data.Fraction;
                }

                return(result);
            }, fsWorldCoordA, fsWorldCoordB);

            firstHit = firstHitLocal;
            return(firstHitFraction != float.MaxValue);
        }
Beispiel #2
0
        private void HorizontalCollisions(ref Vector2 velocity)
        {
            var directionX = MathF.Sign(velocity.X);
            var rayLength  = MathF.Abs(velocity.X) + SkinWidth;

            for (var i = 0; i < HorizontalRayCount; i++)
            {
                var rayOrigin = directionX == -1 ? raycastOrigins.bottomLeft : raycastOrigins.bottomRight;
                rayOrigin -= Vector2.UnitY * (horizontalRaySpacing * i);

                if (DualityApp.ExecEnvironment == DualityApp.ExecutionEnvironment.Editor)
                {
                    VisualLog.Default.DrawVector(rayOrigin.X, rayOrigin.Y, 0, directionX * rayLength, 0);
                }

                RayCastCallback raycastCallback = data => 1.0f;
                RayCastData     rayCastData;

                if (RigidBody.RayCast(rayOrigin, rayOrigin + Vector2.UnitX * directionX * rayLength, raycastCallback,
                                      out rayCastData))
                {
                    var distance = (rayOrigin - rayCastData.Pos).Length;

                    velocity.X = (distance - SkinWidth) * directionX;
                    rayLength  = distance;

                    collisions.right = directionX == 1;
                    collisions.left  = directionX == -1;
                }
            }
        }
Beispiel #3
0
        public override void  Step()
        {
            bool advanceRay = TestSettings.pause == false || TestSettings.singleStep;

            base.Step();

            float L      = 11.0f;
            Vec2  point1 = new Vec2(0.0f, 10.0f);
            Vec2  d      = new Vec2(L * (float)Math.Cos(m_angle), L * (float)Math.Sin(m_angle));
            Vec2  point2 = point1 + d;

            if (m_mode == Mode.e_closest)
            {
                _callback = new RayCastClosestCallback();
                m_world.RayCast(_callback, point1, point2);
            }
            else if (m_mode == Mode.e_any)
            {
                _callback = new RayCastAnyCallback();
                m_world.RayCast(_callback, point1, point2);
            }
            else if (m_mode == Mode.e_multiple)
            {
                _callback = new RayCastMultipleCallback();
                m_world.RayCast(_callback, point1, point2);
            }

            if (advanceRay)
            {
                m_angle += (float)(0.25 * Math.PI / 180.0);
            }
        }
Beispiel #4
0
        private void VerticalCollisions(ref Vector2 velocity)
        {
            var directionY = MathF.Sign(velocity.Y);
            var rayLength  = MathF.Abs(velocity.Y) + SkinWidth;

            for (var i = 0; i < VerticalRayCount; i++)
            {
                var rayOrigin = directionY == -1 ? raycastOrigins.topLeft : raycastOrigins.bottomLeft;
                rayOrigin += Vector2.UnitX * (verticalRaySpacing * i + velocity.X);

                if (DualityApp.ExecEnvironment == DualityApp.ExecutionEnvironment.Editor)
                {
                    VisualLog.Default.DrawVector(rayOrigin.X, rayOrigin.Y, 0, 0, directionY * rayLength);
                }

                RayCastCallback raycastCallback = data => 1.0f;
                RayCastData     rayCastData;

                if (RigidBody.RayCast(rayOrigin, rayOrigin + Vector2.UnitY * directionY * rayLength, raycastCallback,
                                      out rayCastData))
                {
                    var distance = (rayOrigin - rayCastData.Pos).Length;
                    velocity.Y = (distance - SkinWidth) * directionY;
                    rayLength  = distance;

                    collisions.below = directionY == 1;
                    collisions.above = directionY == -1;
                }
            }
        }
Beispiel #5
0
        public void CheckCanSeePlayer(Vector2 point)
        {
            CanSeePlayer = true;
            RayCastCallback callback = new RayCastCallback(RayCastCallback);

            world.RayCast(callback, point, SolitudeScreen.ship.Player.body.Position);
        }
Beispiel #6
0
        /// <summary>
        /// Ray-cast the world for all fixtures in the path of the ray. Your callback
        /// controls whether you get the closest point, any point, or n-points.
        /// The ray-cast ignores shapes that contain the starting point.
        ///
        /// Inside the callback:
        /// return -1: ignore this fixture and continue
        /// return 0: terminate the ray cast
        /// return fraction: clip the ray to this point
        /// return 1: don't clip the ray and continue
        /// </summary>
        /// <param name="callback">A user implemented callback class.</param>
        /// <param name="point1">The ray starting point.</param>
        /// <param name="point2">The ray ending point.</param>
        public void RayCast(RayCastCallback callback, Vector2 point1, Vector2 point2)
        {
            RayCastInput input = new RayCastInput();

            input.MaxFraction = 1.0f;
            input.Point1      = point1;
            input.Point2      = point2;

            this.ContactManager.BroadPhase.RayCast((rayCastInput, proxyId) =>
            {
                FixtureProxy proxy = this.ContactManager.BroadPhase.GetProxy(proxyId);
                Fixture fixture    = proxy.Fixture;
                int index          = proxy.ChildIndex;
                RayCastOutput output;
                bool hit = fixture.RayCast(out output, ref rayCastInput, index);

                if (hit)
                {
                    float fraction = output.Fraction;
                    Vector2 point  = (1.0f - fraction) * rayCastInput.Point1 + fraction * rayCastInput.Point2;
                    return(callback(fixture, point, output.Normal, fraction));
                }

                return(rayCastInput.MaxFraction);                //input.MaxFraction;
            }, ref input);
        }
Beispiel #7
0
        public bool TryDrill(Vector2 direction)
        {
            if (direction == Vector2.Zero)
            {
                return(false);
            }

            Vector2 rayOrigin = GameObj.Transform.Pos.Xy;
            Vector2 rayEnd    = rayOrigin + direction.Normalized * DrillDistance;

            RayCastCallback rayCB = data => {
                if (data.GameObj.GetComponent <TilemapCollider> () != null)
                {
                    return(1.0f);
                }
                else
                {
                    return(-1.0f);
                }
            };

            RayCastData rayCastData;

            if (RigidBody.RayCast(rayOrigin, rayEnd, rayCB, out rayCastData))
            {
                DoDrill(rayCastData, direction);
                return(true);
            }
            return(false);
        }
Beispiel #8
0
        public void Jump()
        {
            if (Jumping || (Crouching && !CrouchHeadroomHitTest()))
            {
                return;
            }
            RayCastCallback callback = (fixture, point, normal, fraction) => {
                lock (_RenderSet.Scene.Game.UpdateLock)
                {
                    // TODO: Have these values be not hard-coded
                    if (fixture == FixtureUpper || fixture == FixtureLower)
                    {
                        return(1.0f);
                    }

                    //if(JumpTimer.Elapsed.TotalMilliseconds > 50 && GoneDown)
                    if (!Jumping)
                    {
                        JumpTimer.Restart();
                        Body.LinearVelocity = new Microsoft.Xna.Framework.Vector2(Body.LinearVelocity.X, _JumpAmount);
                        GoneDown            = false;
                        PlayAnimation(AnimationPreJump);
                        _AnimationNext = new Lazy <SpriteAnimation>(() => { return(AnimationJumping); });

                        // HIGH JUMP
                        //FixtureLower.CollisionCategories = Category.None;
                        //FixtureUpper.CollisionCategories = Category.Cat1;
                    }

                    if (FixtureLower.CollisionCategories == Category.None)
                    {
                        // TODO: Give this functionality to more than just the player class
                        // This code is VERY important; this code tells all of the objects
                        // currently touching the lower fixture to separate as the fixture
                        // is marked as non-colliding. This ensures things like floor switches
                        // don't get stuck closed!
                        FixtureLowerColliders.Add(fixture);
                        FixtureLowerColliders.ForEach(c => {
                            if (FixtureLower.OnSeparation != null)
                            {
                                FixtureLower.OnSeparation(FixtureLower, c);
                            }
                            if (c.OnSeparation != null)
                            {
                                c.OnSeparation(c, FixtureLower);
                            }
                            //Console.WriteLine (c.Body.UserData);
                        });
                        FixtureLowerColliders.Clear();
                    }

                    return(1.0f);
                }
            };

            lock (_RenderSet.Scene.Game.UpdateLock) // Paranoid
                BodyPlatformRayCast(callback);
        }
Beispiel #9
0
        /// Ray-cast the world for all fixtures in the path of the ray. Your callback
        /// controls whether you get the closest point, any point, or n-points.
        /// The ray-cast ignores shapes that contain the starting point.
        /// @param callback a user implemented callback class.
        /// @param point1 the ray starting point
        /// @param point2 the ray ending point
        public void RayCast(RayCastCallback callback, Vector2 point1, Vector2 point2)
        {
            RayCastInput input = new RayCastInput();

            input.maxFraction = 1.0f;
            input.p1          = point1;
            input.p2          = point2;

            _rayCastCallback = callback;
            _contactManager._broadPhase.RayCast(_rayCastCallbackWrapper, ref input);
            _rayCastCallback = null;
        }
Beispiel #10
0
 /// <summary>
 /// 反註冊RayCastMgr
 /// </summary>
 /// <param name="rayCastCb">callback</param>
 /// <returns></returns>
 public bool UnRegister(RayCastCallback rayCastCb)
 {
     if (rayDic.ContainsKey(rayCastCb))
     {
         cbFunction -= rayCastCb;
         rayDic.Remove(rayCastCb);
         ResetLayerMask();
         return(true);
     }
     else
     {
         return(false);
     }
 }
Beispiel #11
0
 public void RayCast(RayCastCallback callback, Microsoft.Xna.Framework.Vector2 point1, Microsoft.Xna.Framework.Vector2 point2)
 {
     World.RayCast(callback, point1, point2);
     if (Configuration.DrawBlueprints)
     {
         lock (_RenderLock)
         {
             new BlueprintLine(
                 new Vector3d(point1.X * Configuration.MeterInPixels, point1.Y * Configuration.MeterInPixels, 0.0),
                 new Vector3d(point2.X * Configuration.MeterInPixels, point2.Y * Configuration.MeterInPixels, 0.0),
                 WorldBlueprint);
         }
     }
 }
Beispiel #12
0
 /// <summary>
 /// 註冊RayCastMgr
 /// </summary>
 /// <param name="layers">layer name</param>
 /// <param name="rayCastCb">callback(RaycastHit[] rayCastHit)</param>
 /// <returns></returns>
 public bool Register(string[] layers, RayCastCallback rayCastCb)
 {
     if (!rayDic.ContainsKey(rayCastCb))
     {
         cbFunction += rayCastCb;
         rayDic.Add(rayCastCb, layers);
         ResetLayerMask();
         return(true);
     }
     else
     {
         return(false);
     }
 }
Beispiel #13
0
        /// <summary>
        /// Performs a 2d physical raycast in world coordinates.
        /// </summary>
        /// <param name="start">The starting point in world coordinates.</param>
        /// <param name="end">The desired end point in world coordinates.</param>
        /// <param name="callback">
        /// The callback that is invoked for each hit on the raycast. Note that the order in which each hit occurs isn't deterministic
        /// and may appear random. Return -1 to ignore the curret shape, 0 to terminate the raycast, data.Fraction to clip the ray for current hit, or 1 to continue.
        /// </param>
        public void RayCast(Vector2 start, Vector2 end, RayCastCallback callback)
        {
            if (callback == null)
            {
                callback = RayCast_DefaultCallback;
            }

            Vector2 fsWorldCoordA = PhysicsUnit.LengthToPhysical * start;
            Vector2 fsWorldCoordB = PhysicsUnit.LengthToPhysical * end;

            this.native.RayCast(delegate(Fixture fixture, Vector2 pos, Vector2 normal, float fraction)
            {
                return(callback(new RayCastData(
                                    fixture.UserData as ShapeInfo,
                                    PhysicsUnit.LengthToDuality * pos,
                                    normal,
                                    fraction)));
            }, fsWorldCoordA, fsWorldCoordB);
        }
Beispiel #14
0
    public void RayCast(Vector3 from, Vector3 to, RayCastCallback callback)
    {
        var rayBounding = BoundingVolume.TowPoints(from, to);
        var v           = FindOrthogonal((to - from).normalized);
        var abs_v       = new Vector3(Mathf.Abs(v.x), Mathf.Abs(v.y), Mathf.Abs(v.z));

        var stack = new Stack <int> ();

        stack.Push(rootNode);
        while (stack.Count > 0)
        {
            var index = stack.Pop();
            if (!BoundingVolume.Intersects(rayBounding, nodes[index].bounding))
            {
                continue;
            }

            var c          = nodes[index].bounding.center;
            var h          = nodes[index].bounding.extents;
            var separation = Mathf.Abs(Vector3.Dot(v, from - c)) - Vector3.Dot(abs_v, h);
            if (separation > 0.0f)
            {
                continue;
            }

            if (nodes[index].isLeaf)
            {
                if (callback != null)
                {
                    callback.Invoke(from, to, nodes[index]);
                    // TODO: Fraction update
                }
            }
            else
            {
                stack.Push(nodes[index].childA);
                stack.Push(nodes[index].childB);
            }
        }
    }
Beispiel #15
0
        /// <summary>
        /// Performs a 2d physical raycast in world coordinates.
        /// </summary>
        /// <param name="start">The starting point in world coordinates.</param>
        /// <param name="end">The desired end point in world coordinates.</param>
        /// <param name="callback">
        /// The callback that is invoked for each hit on the raycast. Note that the order in which each hit occurs isn't deterministic
        /// and may appear random. Return -1 to ignore the curret shape, 0 to terminate the raycast, data.Fraction to clip the ray for current hit, or 1 to continue.
        /// </param>
        /// <param name="hits">
        /// A list that will be filled with all hits that were registered, ordered by their Fraction value.
        /// The list will not be cleared before adding items.
        /// </param>
        /// <returns>Returns whether any new hit was registered.</returns>
        public bool RayCast(Vector2 start, Vector2 end, RayCastCallback callback, RawList <RayCastData> hits)
        {
            if (callback == null)
            {
                callback = RayCast_DefaultCallback;
            }

            Vector2 fsWorldCoordA = PhysicsUnit.LengthToPhysical * start;
            Vector2 fsWorldCoordB = PhysicsUnit.LengthToPhysical * end;

            int oldResultCount = hits.Count;

            this.native.RayCast(delegate(Fixture fixture, Vector2 pos, Vector2 normal, float fraction)
            {
                int index          = hits.Count++;
                RayCastData[] data = hits.Data;

                data[index] = new RayCastData(
                    fixture.UserData as ShapeInfo,
                    PhysicsUnit.LengthToDuality * pos,
                    normal,
                    fraction);

                float result = callback(data[index]);
                if (result < 0.0f)
                {
                    hits.Count--;
                }

                return(result);
            }, fsWorldCoordA, fsWorldCoordB);

            hits.Data.StableSort(
                0,
                hits.Count,
                (d1, d2) => (int)(1000000.0f * (d1.Fraction - d2.Fraction)));
            return(hits.Count > oldResultCount);
        }
Beispiel #16
0
        public void BodyPlatformRayCast(RayCastCallback callback)
        {
            // TODO: make the foot reach distance (in pixels) a member variable
            AABB aabb;

            lock (Body) {             // Paraoid...
                if (FixtureLower.CollisionCategories == Category.None && Jumping)
                {
                    FixtureUpper.GetAABB(out aabb, 0);
                }
                else
                {
                    FixtureLower.GetAABB(out aabb, 0);                      // Probably disabled lower fixture during jump
                }
            }
            float w = aabb.UpperBound.X - aabb.LowerBound.X;
            float h = aabb.UpperBound.Y - aabb.LowerBound.Y;

            float pixel = 1.0f / (float)Configuration.MeterInPixels;

            float px = (float)PositionX * pixel;
            float py = (float)PositionY * pixel;

            float x_start = 0.0f;
            float spread  = 3.0f * pixel;
            float y_start = aabb.LowerBound.Y + spread - pixel;
            float y_end   = aabb.LowerBound.Y - spread - pixel;

            for (int i = 0; i < JumpRayXDirections.Length; i++)
            {
                float dx    = (float)(_Scale.X * w * JumpRayXDirections [i]);
                var   start = new Microsoft.Xna.Framework.Vector2(px + x_start + dx, py + y_start);
                var   end   = new Microsoft.Xna.Framework.Vector2(start.X, py + y_end);
                _RenderSet.Scene.RayCast(callback, start, end);
            }
        }
Beispiel #17
0
		/// <summary>
		/// Performs a 2d physical raycast in world coordinates.
		/// </summary>
		/// <param name="start">The starting point in world coordinates.</param>
		/// <param name="end">The desired end point in world coordinates.</param>
		/// <param name="callback">
		/// The callback that is invoked for each hit on the raycast. Note that the order in which each hit occurs isn't deterministic
		/// and may appear random. Return -1 to ignore the curret shape, 0 to terminate the raycast, data.Fraction to clip the ray for current hit, or 1 to continue.
		/// </param>
		public static void RayCast(Vector2 start, Vector2 end, RayCastCallback callback)
		{
			if (callback == null) callback = Raycast_DefaultCallback;

			Vector2 fsWorldCoordA = PhysicsUnit.LengthToPhysical * start;
			Vector2 fsWorldCoordB = PhysicsUnit.LengthToPhysical * end;

			Scene.PhysicsWorld.RayCast(delegate(Fixture fixture, Vector2 pos, Vector2 normal, float fraction)
			{
				return callback(new RayCastData(
					fixture.UserData as ShapeInfo, 
					PhysicsUnit.LengthToDuality * pos, 
					normal, 
					fraction));
			}, fsWorldCoordA, fsWorldCoordB);
		}
Beispiel #18
0
        /// Ray-cast against the proxies in the tree. This relies on the callback
        /// to perform a exact ray-cast in the case were the proxy contains a shape.
        /// The callback also performs the any collision filtering. This has performance
        /// roughly equal to k * log(n), where k is the number of collisions and n is the
        /// number of proxies in the tree.
        /// @param input the ray-cast input data. The ray extends from p1 to p1 + maxFraction * (p2 - p1).
        /// @param callback a callback class that is called for each proxy that is hit by the ray.
        public void RayCast(RayCastCallback callback, ref RayCastInput input)
        {
            Vector2 p1 = input.p1;
            Vector2 p2 = input.p2;
            Vector2 r  = p2 - p1;

            Debug.Assert(r.LengthSquared() > 0.0f);
            r.Normalize();

            // v is perpendicular to the segment.
            Vector2 v     = MathUtils.Cross(1.0f, r);
            Vector2 abs_v = MathUtils.Abs(v);

            // Separating axis for segment (Gino, p80).
            // |dot(v, p1 - c)| > dot(|v|, h)

            float maxFraction = input.maxFraction;

            // Build a bounding box for the segment.
            AABB segmentAABB = new AABB();
            {
                Vector2 t = p1 + maxFraction * (p2 - p1);
                segmentAABB.lowerBound = Vector2.Min(p1, t);
                segmentAABB.upperBound = Vector2.Max(p1, t);
            }

            int count = 0;

            stack[count++] = _root;

            while (count > 0)
            {
                int nodeId = stack[--count];
                if (nodeId == NullNode)
                {
                    continue;
                }

                DynamicTreeNode node = _nodes[nodeId];

                if (AABB.TestOverlap(ref node.aabb, ref segmentAABB) == false)
                {
                    continue;
                }

                // Separating axis for segment (Gino, p80).
                // |dot(v, p1 - c)| > dot(|v|, h)
                Vector2 c          = node.aabb.GetCenter();
                Vector2 h          = node.aabb.GetExtents();
                float   separation = Math.Abs(Vector2.Dot(v, p1 - c)) - Vector2.Dot(abs_v, h);
                if (separation > 0.0f)
                {
                    continue;
                }

                if (node.IsLeaf())
                {
                    RayCastInput subInput;
                    subInput.p1          = input.p1;
                    subInput.p2          = input.p2;
                    subInput.maxFraction = maxFraction;

                    RayCastOutput output;

                    callback(out output, ref subInput, node.userData);

                    if (output.hit)
                    {
                        // Early exit.
                        if (output.fraction == 0.0f)
                        {
                            return;
                        }

                        maxFraction = output.fraction;

                        // Update segment bounding box.
                        {
                            Vector2 t = p1 + maxFraction * (p2 - p1);
                            segmentAABB.lowerBound = Vector2.Min(p1, t);
                            segmentAABB.upperBound = Vector2.Max(p1, t);
                        }
                    }
                }
                else
                {
                    Debug.Assert(count + 1 < k_stackSize);
                    stack[count++] = node.child1;
                    stack[count++] = node.child2;
                }
            }
        }
Beispiel #19
0
		/// <summary>
		/// Performs a 2d physical raycast in world coordinates.
		/// </summary>
		/// <param name="worldCoordA">The starting point.</param>
		/// <param name="worldCoordB">The desired end point.</param>
		/// <param name="callback">
		/// The callback that is invoked for each hit on the raycast. Note that the order in which each hit occurs isn't deterministic
		/// and may appear random. Return -1 to ignore the curret shape, 0 to terminate the raycast, data.Fraction to clip the ray for current hit, or 1 to continue.
		/// </param>
		/// <returns>Returns a list of all occurred hits, ordered by their Fraction value.</returns>
		public static List<RayCastData> RayCast(Vector2 worldCoordA, Vector2 worldCoordB, RayCastCallback callback = null)
		{
			if (callback == null) callback = Raycast_DefaultCallback;
			Vector2 fsWorldCoordA = PhysicsConvert.ToPhysicalUnit(worldCoordA);
			Vector2 fsWorldCoordB = PhysicsConvert.ToPhysicalUnit(worldCoordB);
			List<RayCastData> hitData = new List<RayCastData>();
			Scene.PhysicsWorld.RayCast(delegate(Fixture fixture, Vector2 pos, Vector2 normal, float fraction)
			{
				RayCastData data = new RayCastData(
					fixture.UserData as ShapeInfo, 
					PhysicsConvert.ToDualityUnit(pos), 
					normal, 
					fraction);
				float result = callback(data);
				if (result >= 0.0f) hitData.Add(data);
				return result;
			}, fsWorldCoordA, fsWorldCoordB);
			hitData.StableSort((d1, d2) => (int)(1000000.0f * (d1.Fraction - d2.Fraction)));
			return hitData;
		}
Beispiel #20
0
        public void RayCast(RayCastCallback callback, Vector2 start, Vector2 end, bool ignoreSensors = true, bool ignoreProjectile = true)
        {
            // Use Bresenham's line algorithm to check cells along the ray          IMPROVE THAT AS IT'S NOT 100% RELIABLE BRESENHAM CELLS DON'T CATCH ALL POSSIBLE COLLIDERS NEEDS MORE THAN ONE CELL THICK       !!! !!! !!!
            //

            Line line = new Line(start, end);

            _drawLines.Add(line);

            // Get starting end and positions.
            Vector2 pos1 = start - Origin;
            Vector2 pos2 = end - Origin;
            int     x1 = (int)(pos1.X / _cellSize); int x2 = (int)(pos2.X / _cellSize);
            int     y1 = (int)(pos1.Y / _cellSize); int y2 = (int)(pos2.Y / _cellSize);

            int deltaX = Math.Abs(x1 - x2);
            int deltaY = Math.Abs(y1 - y2);

            // Set signum values.
            int signX = x1 < x2 ? 1 : -1;
            int signY = y1 < y2 ? 1 : -1;

            int error = deltaX - deltaY;

            bool bFirst = true;

            while (true)
            {
                bool bLast = (x1 == x2 && y1 == y2);

                // Stop if we found the collision.
                if (CheckLineCollisions(x1, y1, line, callback, bFirst, bLast, ignoreSensors, ignoreProjectile))
                {
                    break;
                }

                // If we reached last cell break out of loop.
                if (bLast)
                {
                    break;
                }
                if (bFirst)
                {
                    bFirst = false;
                }

                // Double error to avoid using floats.
                int doubleError = error * 2;

                if (doubleError > -deltaY)
                {
                    // Check cells inbetween to make sure.
                    int y1b = y1 + signY;
                    if (checkLineInCell(x1, y1b, line))
                    {
                        if (CheckLineCollisions(x1, y1b, line, callback, bFirst, bLast, ignoreSensors, ignoreProjectile))
                        {
                            break;
                        }
                    }

                    // Increment in x direction.
                    error -= deltaY;
                    x1    += signX;
                }
                if (doubleError < deltaX)
                {
                    // Check cells inbetween to make sure.
                    int x1b = x1 + signX;
                    if (checkLineInCell(x1b, y1, line))
                    {
                        if (CheckLineCollisions(x1 + signX, y1, line, callback, bFirst, bLast, ignoreSensors, ignoreProjectile))
                        {
                            break;
                        }
                    }

                    // Increment in y direction.
                    error += deltaX;
                    y1    += signY;
                }
            }
        }
Beispiel #21
0
 public void RayCast(RayCastCallback callback, Microsoft.Xna.Framework.Vector2 point1, Microsoft.Xna.Framework.Vector2 point2)
 {
     _World.RayCast (callback, point1, point2);
     if (Configuration.DrawBlueprints) {
         lock(RenderLock)
         {
             new BlueprintLine (
             new Vector3d (point1.X * Configuration.MeterInPixels, point1.Y * Configuration.MeterInPixels, 0.0),
             new Vector3d (point2.X * Configuration.MeterInPixels, point2.Y * Configuration.MeterInPixels, 0.0),
                 WorldBlueprint);
         }
     }
 }
Beispiel #22
0
        public void BodyPlatformRayCast(RayCastCallback callback)
        {
            // TODO: make the foot reach distance (in pixels) a member variable
            AABB aabb;
            lock (Body) { // Paraoid...
                if(FixtureLower.CollisionCategories == Category.None && Jumping)
                    FixtureUpper.GetAABB (out aabb, 0);
                else
                    FixtureLower.GetAABB (out aabb, 0); // Probably disabled lower fixture during jump
            }
            float w = aabb.UpperBound.X - aabb.LowerBound.X;
            float h = aabb.UpperBound.Y - aabb.LowerBound.Y;

            float pixel = 1.0f / (float)Configuration.MeterInPixels;

            float px = (float)PositionX * pixel;
            float py = (float)PositionY * pixel;

            float x_start = 0.0f;
            float spread = 3.0f * pixel;
            float y_start = aabb.LowerBound.Y + spread;
            float y_end = aabb.LowerBound.Y - spread;

            for (int i = 0; i < JumpRayXDirections.Length; i++) {
                float dx = (float)(_Scale.X * w * JumpRayXDirections [i]);
                var start = new Microsoft.Xna.Framework.Vector2 (px + x_start + dx, py + y_start);
                var end = new Microsoft.Xna.Framework.Vector2 (start.X, py + y_end);
                _RenderSet.Scene.RayCast (callback, start, end);
            }
        }
Beispiel #23
0
        /// <summary>
        /// Ray-cast the world for all fixtures in the path of the ray. Your callback
        /// controls whether you get the closest point, any point, or n-points.
        /// The ray-cast ignores shapes that contain the starting point.
        /// 
        /// Inside the callback:
        /// return -1: ignore this fixture and continue
        /// return 0: terminate the ray cast
        /// return fraction: clip the ray to this point
        /// return 1: don't clip the ray and continue
        /// </summary>
        /// <param name="callback">A user implemented callback class.</param>
        /// <param name="point1">The ray starting point.</param>
        /// <param name="point2">The ray ending point.</param>
        public void RayCast(RayCastCallback callback, Vector2 point1, Vector2 point2)
        {
            RayCastInput input = new RayCastInput();
            input.MaxFraction = 1.0f;
            input.Point1 = point1;
            input.Point2 = point2;

            ContactManager.BroadPhase.RayCast((rayCastInput, proxyId) =>
                                                  {
                                                      FixtureProxy proxy = ContactManager.BroadPhase.GetProxy(proxyId);
                                                      Fixture fixture = proxy.Fixture;
                                                      int index = proxy.ChildIndex;
                                                      RayCastOutput output;
                                                      bool hit = fixture.RayCast(out output, ref rayCastInput, index);

                                                      if (hit)
                                                      {
                                                          float fraction = output.Fraction;
                                                          Vector2 point = (1.0f - fraction) * input.Point1 +
                                                                          fraction * input.Point2;
                                                          return callback(fixture, point, output.Normal, fraction);
                                                      }

                                                      return input.MaxFraction;
                                                  }, ref input);
        }
Beispiel #24
0
 public void CheckCanSeePlayer(Vector2 point)
 {
     CanSeePlayer = true;
     RayCastCallback callback = new RayCastCallback(RayCastCallback);
     world.RayCast(callback, point, SolitudeScreen.ship.Player.body.Position);
 }
Beispiel #25
0
 /// <summary>
 /// 反註冊RayCastMgr
 /// </summary>
 /// <param name="rayCastCb">callback</param>
 /// <returns></returns>
 public bool UnRegister( RayCastCallback rayCastCb)
 {
     if (rayDic.ContainsKey(rayCastCb))
     {
         cbFunction -= rayCastCb;
         rayDic.Remove(rayCastCb);
         ResetLayerMask();
         return true;
     }
     else
     {
         return false;
     }
 }
Beispiel #26
0
        /// Ray-cast against the proxies in the tree. This relies on the callback
        /// to perform a exact ray-cast in the case were the proxy contains a shape.
        /// The callback also performs the any collision filtering. This has performance
        /// roughly equal to k * log(n), where k is the number of collisions and n is the
        /// number of proxies in the tree.
        /// @param input the ray-cast input data. The ray extends from p1 to p1 + maxFraction * (p2 - p1).
        /// @param callback a callback class that is called for each proxy that is hit by the ray.
        public void RayCast(RayCastCallback callback, ref RayCastInput input)
        {
            Vector2 p1 = input.p1;
            Vector2 p2 = input.p2;
            Vector2 r = p2 - p1;
            Debug.Assert(r.LengthSquared() > 0.0f);
            r.Normalize();

            // v is perpendicular to the segment.
            Vector2 v = MathUtils.Cross(1.0f, r);
            Vector2 abs_v = MathUtils.Abs(v);

            // Separating axis for segment (Gino, p80).
            // |dot(v, p1 - c)| > dot(|v|, h)

            float maxFraction = input.maxFraction;

            // Build a bounding box for the segment.
            AABB segmentAABB = new AABB();
            {
                Vector2 t = p1 + maxFraction * (p2 - p1);
                segmentAABB.lowerBound = Vector2.Min(p1, t);
                segmentAABB.upperBound = Vector2.Max(p1, t);
            }

            int count = 0;
            stack[count++] = _root;

            while (count > 0)
            {
                int nodeId = stack[--count];
                if (nodeId == NullNode)
                {
                    continue;
                }

                DynamicTreeNode node = _nodes[nodeId];

                if (AABB.TestOverlap(ref node.aabb, ref segmentAABB) == false)
                {
                    continue;
                }

                // Separating axis for segment (Gino, p80).
                // |dot(v, p1 - c)| > dot(|v|, h)
                Vector2 c = node.aabb.GetCenter();
                Vector2 h = node.aabb.GetExtents();
                float separation = Math.Abs(Vector2.Dot(v, p1 - c)) - Vector2.Dot(abs_v, h);
                if (separation > 0.0f)
                {
                    continue;
                }

                if (node.IsLeaf())
                {
                    RayCastInput subInput;
                    subInput.p1 = input.p1;
                    subInput.p2 = input.p2;
                    subInput.maxFraction = maxFraction;

                    RayCastOutput output;

                    callback(out output, ref subInput, node.userData);

                    if (output.hit)
                    {
                        // Early exit.
                        if (output.fraction == 0.0f)
                        {
                            return;
                        }

                        maxFraction = output.fraction;

                        // Update segment bounding box.
                        {
                            Vector2 t = p1 + maxFraction * (p2 - p1);
                            segmentAABB.lowerBound = Vector2.Min(p1, t);
                            segmentAABB.upperBound = Vector2.Max(p1, t);
                        }
                    }
                }
                else
                {
                    Debug.Assert(count + 1 < k_stackSize);
                    stack[count++] = node.child1;
                    stack[count++] = node.child2;
                }
            }
        }
Beispiel #27
0
        public override void Draw()
        {
            base.Draw();

            m_debugDraw.DrawString(5, m_textLine, "Press 1-5 to place stuff, m to change the mode");
            m_textLine += 15;
            m_debugDraw.DrawString(5, m_textLine, "Mode = " + m_mode.ToString());
            m_textLine += 15;

            if (_callback == null)
            {
                return;
            }

            float L      = 11.0f;
            Vec2  point1 = new Vec2(0.0f, 10.0f);
            Vec2  d      = new Vec2(L * (float)Math.Cos(m_angle), L * (float)Math.Sin(m_angle));
            Vec2  point2 = point1 + d;

            if (_callback is RayCastClosestCallback)
            {
                RayCastClosestCallback callback = (RayCastClosestCallback)_callback;
                m_world.RayCast(_callback, point1, point2);

                if (callback.m_hit)
                {
                    m_debugDraw.DrawPoint(callback.m_point, 5.0f, new ColorF(0.4f, 0.9f, 0.4f));
                    m_debugDraw.DrawSegment(point1, callback.m_point, new ColorF(0.8f, 0.8f, 0.8f));
                    Vec2 head = callback.m_point + 0.5f * callback.m_normal;
                    m_debugDraw.DrawSegment(callback.m_point, head, new ColorF(0.9f, 0.9f, 0.4f));
                }
                else
                {
                    m_debugDraw.DrawSegment(point1, point2, new ColorF(0.8f, 0.8f, 0.8f));
                }
            }
            else if (_callback is RayCastAnyCallback)
            {
                RayCastAnyCallback callback = (RayCastAnyCallback)_callback;
                _callback = new RayCastAnyCallback();

                if (callback.m_hit)
                {
                    m_debugDraw.DrawPoint(callback.m_point, 5.0f, new ColorF(0.4f, 0.9f, 0.4f));
                    m_debugDraw.DrawSegment(point1, callback.m_point, new ColorF(0.8f, 0.8f, 0.8f));
                    Vec2 head = callback.m_point + 0.5f * callback.m_normal;
                    m_debugDraw.DrawSegment(callback.m_point, head, new ColorF(0.9f, 0.9f, 0.4f));
                }
                else
                {
                    m_debugDraw.DrawSegment(point1, point2, new ColorF(0.8f, 0.8f, 0.8f));
                }
            }
            else if (_callback is RayCastMultipleCallback)
            {
                RayCastMultipleCallback callback = (RayCastMultipleCallback)_callback;
                m_debugDraw.DrawSegment(point1, point2, new ColorF(0.8f, 0.8f, 0.8f));

                for (int i = 0; i < callback.m_count; ++i)
                {
                    Vec2 p = callback.m_points[i];
                    Vec2 n = callback.m_normals[i];
                    m_debugDraw.DrawPoint(p, 5.0f, new ColorF(0.4f, 0.9f, 0.4f));
                    m_debugDraw.DrawSegment(point1, p, new ColorF(0.8f, 0.8f, 0.8f));
                    Vec2 head = p + 0.5f * n;
                    m_debugDraw.DrawSegment(p, head, new ColorF(0.9f, 0.9f, 0.4f));
                }
            }
        }
Beispiel #28
0
 public RayCastMultipleCallback()
 {
     Count    = 0;
     Callback = ReportFixture;
 }
Beispiel #29
0
 public RayCastAnyCallback()
 {
     Hit      = false;
     Callback = ReportFixture;
 }
Beispiel #30
0
        private bool CheckLineCollisions(int col, int row, Line line, RayCastCallback callback, bool isFirst, bool isLast, bool ignoreSensor, bool ignoreProjectile)
        {
            Bag <PhysicsObject> possibleColliders = _grid[col, row];
            Vector2             collisionPoint    = line.P2;
            Vector2             collisionNormal   = Vector2.Zero;
            PhysicsObject       collidingObject   = null;
            float distance = float.PositiveInfinity;

            if (possibleColliders == null)
            {
                return(false);
            }

            /// I actually don't now why I put this in - it may causes bugs in future but for the moment it seems to work when commented.

            /*if (possibleColliders.Count > 0)
             * {
             *  // Cut out segment within the current cell.
             *  //
             *
             *  // Create a sensor within the cell to collide with
             *  float xCell = (col + 0.5f) * _cellSize + Origin.X;
             *  float yCell = (row + 0.5f) * _cellSize + Origin.Y;
             *
             *  var cellCollider = new Sensor(this, new Vector2(xCell, yCell), new Vector2(_cellSize, _cellSize));
             *
             *  var newStart = Vector2.Zero;
             *  var newEnd = Vector2.Zero;
             *  var newNorm = Vector2.Zero;
             *  var mirrorLine = new Line(line.P2, line.P1);
             *
             *  if (!CollideLinePoly(line, (Polygon)cellCollider.CollisionShape, out newStart, out newNorm))
             *  {
             *      newStart = line.P1;
             *  }
             *  if (!CollideLinePoly(mirrorLine, (Polygon)cellCollider.CollisionShape, out newEnd, out newNorm))
             *  {
             *      newEnd = line.P2;
             *  }
             *
             *  line = new Line(newStart, newEnd);
             *
             *  cellCollider.Dispense(); // Remove from world
             * }*/

            // Test each object to collide with line.
            possibleColliders.ForEachWith((collider) =>
            {
                if (ignoreSensor)
                {
                    if (collider.IsSensor)
                    {
                        return;
                    }
                }

                if (ignoreProjectile)
                {
                    if (collider.IsProjectile)
                    {
                        return;
                    }
                }

                if (collider.CollisionShape.Type == Shape.ShapeType.SH_POLYGON)
                {
                    var poly = collider.CollisionShape as Polygon;
                    if (isFirst)
                    {
                        if (CollidePointPoly(line.P1, poly))
                        {
                            return;
                        }
                    }

                    Vector2 curCollisionPoint, curCollisionNormal;
                    if (CollideLinePoly(line, poly, out curCollisionPoint, out curCollisionNormal))
                    {
                        // Check for closest point
                        float curDistance = (curCollisionPoint - line.P1).Length();
                        if (curDistance < distance)
                        {
                            distance        = curDistance;
                            collidingObject = collider;
                            collisionPoint  = curCollisionPoint;
                            collisionNormal = curCollisionNormal;
                        }
                    }
                }
            }, (collider) => { return(collider.IsActive); });

            if (collidingObject != null)
            {
                callback(collidingObject, collisionPoint, collisionNormal);
                _drawPoints.Add(collisionPoint);
                return(true);
            }

            return(false);
        }
Beispiel #31
0
		/// <summary>
		/// Performs a 2d physical raycast in world coordinates.
		/// </summary>
		/// <param name="start">The starting point in world coordinates.</param>
		/// <param name="end">The desired end point in world coordinates.</param>
		/// <param name="callback">
		/// The callback that is invoked for each hit on the raycast. Note that the order in which each hit occurs isn't deterministic
		/// and may appear random. Return -1 to ignore the curret shape, 0 to terminate the raycast, data.Fraction to clip the ray for current hit, or 1 to continue.
		/// </param>
		/// <param name="hits">Returns a list of all occurred hits, ordered by their Fraction value.</param>
		public static void RayCast(Vector2 start, Vector2 end, RayCastCallback callback, out RawList<RayCastData> hits)
		{
			if (callback == null) callback = Raycast_DefaultCallback;

			Vector2 fsWorldCoordA = PhysicsUnit.LengthToPhysical * start;
			Vector2 fsWorldCoordB = PhysicsUnit.LengthToPhysical * end;

			RawList<RayCastData> localHits = new RawList<RayCastData>();
			Scene.PhysicsWorld.RayCast(delegate(Fixture fixture, Vector2 pos, Vector2 normal, float fraction)
			{
				int oldCount = localHits.Count++;
				RayCastData[] data = localHits.Data;

				data[oldCount] = new RayCastData(
					fixture.UserData as ShapeInfo, 
					PhysicsUnit.LengthToDuality * pos, 
					normal, 
					fraction);

				float result = callback(data[oldCount]);
				if (result < 0.0f)
					localHits.Count--;

				return result;
			}, fsWorldCoordA, fsWorldCoordB);
			localHits.Data.StableSort(0, localHits.Count, (d1, d2) => (int)(1000000.0f * (d1.Fraction - d2.Fraction)));

			hits = localHits;
		}
Beispiel #32
0
 /// <summary>
 /// 註冊RayCastMgr
 /// </summary>
 /// <param name="layers">layer name</param>
 /// <param name="rayCastCb">callback(RaycastHit[] rayCastHit)</param>
 /// <returns></returns>
 public bool Register(string[] layers, RayCastCallback rayCastCb)
 {
     if (!rayDic.ContainsKey(rayCastCb))
     {
         cbFunction += rayCastCb;
         rayDic.Add(rayCastCb, layers);
         ResetLayerMask();
         return true;
     }
     else
     {
         return false;
     }
 }
Beispiel #33
0
		/// <summary>
		/// Performs a 2d physical raycast in world coordinates.
		/// </summary>
		/// <param name="start">The starting point in world coordinates.</param>
		/// <param name="end">The desired end point in world coordinates.</param>
		/// <param name="callback">
		/// The callback that is invoked for each hit on the raycast. Note that the order in which each hit occurs isn't deterministic
		/// and may appear random. Return -1 to ignore the curret shape, 0 to terminate the raycast, data.Fraction to clip the ray for current hit, or 1 to continue.
		/// </param>
		/// <param name="firstHit">Returns the first hit that occurs, i.e. the one with the highest proximity to the starting point.</param>
		/// <returns>Returns whether anything has been hit.</returns>
		public static bool RayCast(Vector2 start, Vector2 end, RayCastCallback callback, out RayCastData firstHit)
		{
			if (callback == null) callback = Raycast_DefaultCallback;

			Vector2 fsWorldCoordA = PhysicsUnit.LengthToPhysical * start;
			Vector2 fsWorldCoordB = PhysicsUnit.LengthToPhysical * end;

			float firstHitFraction = float.MaxValue;
			RayCastData firstHitLocal = default(RayCastData);

			Scene.PhysicsWorld.RayCast(delegate(Fixture fixture, Vector2 pos, Vector2 normal, float fraction)
			{
				RayCastData data = new RayCastData(
					fixture.UserData as ShapeInfo, 
					PhysicsUnit.LengthToDuality * pos, 
					normal, 
					fraction);

				float result = callback(data);
				if (result >= 0.0f && data.Fraction < firstHitFraction)
				{
					firstHitLocal = data;
					firstHitFraction = data.Fraction;
				}

				return result;
			}, fsWorldCoordA, fsWorldCoordB);

			firstHit = firstHitLocal;
			return firstHitFraction != float.MaxValue;
		}
Beispiel #34
0
    public bool RayCast(Vector3 from, Vector3 to, RayCastCallback callback = null)
    {
        Vector3 r = to - from;

        r.Normalize();

        float maxFraction = 1.0f;

        // v is perpendicular to the segment.
        Vector3 v    = VectorUtil.FindOrthogonal(r).normalized;
        Vector3 absV = VectorUtil.Abs(v);

        // build a bounding box for the segment.
        Aabb rayBounds = Aabb.Empty;

        rayBounds.Include(from);
        rayBounds.Include(to);

        m_stack.Clear();
        m_stack.Push(m_root);

        bool hitAnyBounds = false;

        while (m_stack.Count > 0)
        {
            int index = m_stack.Pop();
            if (index == Null)
            {
                continue;
            }

            if (!Aabb.Intersects(m_nodes[index].Bounds, rayBounds))
            {
                continue;
            }

            // Separating axis for segment (Gino, p80).
            // |dot(v, a - c)| > dot(|v|, h)
            Vector3 c          = m_nodes[index].Bounds.Center;
            Vector3 h          = m_nodes[index].Bounds.HalfExtents;
            float   separation = Mathf.Abs(Vector3.Dot(v, from - c)) - Vector3.Dot(absV, h);
            if (separation > 0.0f)
            {
                continue;
            }

            if (m_nodes[index].IsLeaf)
            {
                Aabb tightBounds = m_nodes[index].Bounds;
                tightBounds.Expand(-FatBoundsRadius);
                float t = tightBounds.RayCast(from, to, maxFraction);
                if (t < 0.0f)
                {
                    continue;
                }

                hitAnyBounds = true;

                float newMaxFraction =
                    callback != null
            ? callback(from, to, m_nodes[index].UserData)
            : maxFraction;

                if (newMaxFraction >= 0.0f)
                {
                    // Update segment bounding box.
                    maxFraction = newMaxFraction;
                    Vector3 newTo = from + maxFraction * (to - from);
                    rayBounds.Min = VectorUtil.Min(from, newTo);
                    rayBounds.Max = VectorUtil.Max(from, newTo);
                }
            }
            else
            {
                m_stack.Push(m_nodes[index].ChildA);
                m_stack.Push(m_nodes[index].ChildB);
            }
        }

        return(hitAnyBounds);
    }
Beispiel #35
0
 /// <summary>
 /// Ray-cast the world for all fixtures in the path of the ray. Your callback controls whether you
 /// get the closest point, any point, or n-points. The ray-cast ignores shapes that contain the
 /// starting point.
 /// </summary>
 /// <param name="callback">a user implemented callback class.</param>
 /// <param name="point1">the ray starting point</param>
 /// <param name="point2">the ray ending point</param>
 public virtual void raycast(RayCastCallback callback, Vec2 point1, Vec2 point2)
 {
     wrcwrapper.broadPhase = m_contactManager.m_broadPhase;
     wrcwrapper.callback = callback;
     input.maxFraction = 1.0f;
     input.p1.set_Renamed(point1);
     input.p2.set_Renamed(point2);
     m_contactManager.m_broadPhase.raycast(wrcwrapper, input);
 }
Beispiel #36
0
 public EdgeShapesCallback()
 {
     Fixture  = null;
     Callback = ReportFixture;
 }
Beispiel #37
0
        /// <summary>
        /// Ray-cast the world for all fixtures in the path of the ray. Your callback
        /// controls whether you get the closest point, any point, or n-points.
        /// The ray-cast ignores shapes that contain the starting point.
        /// </summary>
        /// <param name="callback">A user implemented callback class.</param>
        /// <param name="point1">The ray starting point.</param>
        /// <param name="point2">The ray ending point.</param>
        public void RayCast(RayCastCallback callback, Vector2 point1, Vector2 point2)
        {
            RayCastInput input = new RayCastInput();
            input.MaxFraction = 1.0f;
            input.Point1 = point1;
            input.Point2 = point2;

            _rayCastCallback = callback;
            ContactManager.BroadPhase.RayCast(_rayCastCallbackWrapper, ref input);
            _rayCastCallback = null;
        }
Beispiel #38
0
 /**
    * Ray-cast the world for all fixtures and particles in the path of the ray. Your callback
    * controls whether you get the closest point, any point, or n-points. The ray-cast ignores shapes
    * that contain the starting point.
    *
    * @param callback a user implemented callback class.
    * @param particleCallback the particle callback class.
    * @param point1 the ray starting point
    * @param point2 the ray ending point
    */
 public void raycast(RayCastCallback callback, ParticleRaycastCallback particleCallback,
     Vec2 point1, Vec2 point2)
 {
     wrcwrapper.broadPhase = m_contactManager.m_broadPhase;
     wrcwrapper.callback = callback;
     input.maxFraction = 1.0f;
     input.p1.set(point1);
     input.p2.set(point2);
     m_contactManager.m_broadPhase.raycast(wrcwrapper, input);
     m_particleSystem.raycast(particleCallback, point1, point2);
 }