[C#] Why is t_Enter always 0?

Started by
-1 comments, last by Spa8nky 14 years ago
When colliding with more than one object at the same time, I require the time of collision between two objects in order to resolve the collision correctly. Here I have a test that correctly determines if two AABBs are intersecting, but the swept test using a ray always returns 0.0f for t_Enter:

        private static bool TestAABBAABB(Shape2D s1, Shape2D s2, ref Contact2D contact)
        {
            CD_AABB2D a = (CD_AABB2D)s1;
            CD_AABB2D b = (CD_AABB2D)s2;

            // Minimum Translation Vector parameters
            float mtv_Distance = float.MaxValue;            // Set current minimum distance (max float value so next value is always less)
            Vector2 mtv_Axis = Vector2.Zero;                // Axis along which to travel with the minimum distance

            // Clip length of ray to the segment boundaries
            // Initialise times of first and last contact
            float t_Enter = 0.0f;                           // Time of entry (for ray)
            float t_Exit = 1.0f;                            // Time of exit (for ray)

            if (!IntersectThruAxisSwept(Vector2.UnitX, a, b, ref t_Enter, ref t_Exit, ref mtv_Distance, ref mtv_Axis))
            {
                return false;
            }
            if (!IntersectThruAxisSwept(Vector2.UnitY, a, b, ref t_Enter, ref t_Exit, ref mtv_Distance, ref mtv_Axis))
            {
                return false;
            }

            // Calculate Minimum Translation Vector (MTV)
            Vector2 d = a.Position - b.Position;
            mtv_Axis = Vector2.Dot(d, mtv_Axis) < 0 ? -mtv_Axis : mtv_Axis;

            contact.normal = mtv_Axis;
            contact.penetration = Math.Abs(mtv_Distance) + Math_Util.EPSILON;
            contact.t_Enter = t_Enter;
            contact.t_Exit = t_Exit;

            // Objects are intersecting
            return true;
        }

        private static bool IntersectThruAxisSwept(Vector2 axis, CD_AABB2D a, CD_AABB2D b, ref float t_Enter, ref float t_Exit, ref float mtv_Distance, ref Vector2 mtv_Axis)
        {
            Vector2 v = a.Velocity - b.Velocity;
            if (v.LengthSquared() < 0.0001f)
            {
                return false;
            }

            float a_Min = float.MaxValue;
            float a_Max = float.MinValue;
            float b_Min = float.MaxValue;
            float b_Max = float.MinValue;

            a.CalculateSlab(axis, ref a_Min, ref a_Max);
            b.CalculateSlab(axis, ref b_Min, ref b_Max);

            // Find distance intervals for current two slabs
            // Distance is between slab min/max values
            float d_S0 = a_Min - b_Max;
            float d_S1 = b_Min - a_Max;

            // The distance is positive if the intervals do not overlap
            // Must be >= to 0 and not > 0, otherwise MTV can equal Vector2.Zero and cause NaN
            if (d_S0 > 0f || d_S1 > 0f)
            {
                return false;
            }

            // Current distance interval for slabs [A_Min, A_Max] and [B_Min, B_Max]
            float d = (d_S0 > d_S1) ? -d_S0 : d_S1;

            // If d is the smallest distance so far
            if (Math.Abs(d) < Math.Abs(mtv_Distance))
            {
                // Store the distance and the current axis
                mtv_Distance = d;
                mtv_Axis = axis;
            }

            //===========================================================
            //---[Swept Test]--------------------------------------------
            //===========================================================

            // Convert the slab for B into a 1D ray
            float origin = (b_Max + b_Min) * 0.5f;                          // Origin of ray
            float e = (b_Max - b_Min) * 0.5f;                               // Extent of slab B
            float direction = Vector2.Dot(b.Velocity - a.Velocity, axis);   // Direction of ray (projected onto current axis of separation)

            // Expand the slab for A by the extent of the slab for B
            // This transforms a slab/slab collision test into a ray/slab collision test
            a_Min -= e;
            a_Max += e;

            // Do a 1 dimensional collision check on projected axis
            return RaySlabIntersect(a_Min, a_Max, origin, direction, ref t_Enter, ref t_Exit);
        }

        private static bool RaySlabIntersect(float slab_Min, float slab_Max, float ray_Origin, float ray_End, ref float tb_Enter, ref float tb_Exit)
        {
            float ray_Direction = ray_End - ray_Origin;

            // If ray is parallel to the slab
            if (Math.Abs(ray_Direction) < float.Epsilon)
            {
                // Ray is parallel to slab, but NOT inside the slab
                if (ray_Origin < slab_Min || ray_Origin > slab_Max)
                {
                    return false;
                }
            }
            else
            {
                // Compute intersection t value of ray with near and far plane of slab
                float ood = 1.0f / ray_Direction;
                float ts_Enter = (slab_Min - ray_Origin) * ood;
                float ts_Exit = (slab_Max - ray_Origin) * ood;

                // Make "ts_Enter" be intersection with near plane, "ts_Exit" with far plane
                if (ts_Enter > ts_Exit)
                {
                    Math_Util.Swap(ref ts_Enter, ref ts_Exit);
                }

                // Compute the intersection of slab intersection intervals
                tb_Enter = Math.Max(tb_Enter, ts_Enter);
                tb_Exit = Math.Min(tb_Exit, ts_Exit);

                // Exit with no collision as soon as slab intersection becomes empty
                if (tb_Enter > tb_Exit)
                {
                    return false;
                }
            }

            if (tb_Enter > 0 && tb_Enter < 1)
            {
                Console.WriteLine("STOP");              // NEVER happens, ever!
            }

            return true;
        }

Why am I not getting any collision times, other than 0 for the RaySlabIntersect?

This topic is closed to new replies.

Advertisement