Exemplo n.º 1
0
        /// <summary>
        /// Given a transform, compute the associated axis aligned bounding box for a child shape.
        /// </summary>
        /// <param name="aabb">The aabb results.</param>
        /// <param name="transform">The world transform of the shape.</param>
        /// <param name="childIndex">The child shape index.</param>
        public override void ComputeAABB(out AABB aabb, ref Transform transform, int childIndex)
        {
            FVector2 v1 = MathUtils.Mul(ref transform, _vertex1);
            FVector2 v2 = MathUtils.Mul(ref transform, _vertex2);

            FVector2 lower = FVector2.Min(v1, v2);
            FVector2 upper = FVector2.Max(v1, v2);

            FVector2 r = new FVector2(Radius, Radius);

            aabb.LowerBound = lower - r;
            aabb.UpperBound = upper + r;
        }
Exemplo n.º 2
0
        /// <summary>
        /// Given a transform, compute the associated axis aligned bounding box for a child shape.
        /// </summary>
        /// <param name="aabb">The aabb results.</param>
        /// <param name="transform">The world transform of the shape.</param>
        /// <param name="childIndex">The child shape index.</param>
        public override void ComputeAABB(out AABB aabb, ref Transform transform, int childIndex)
        {
            FVector2 lower = MathUtils.Mul(ref transform, Vertices[0]);
            FVector2 upper = lower;

            for (int i = 1; i < Vertices.Count; ++i)
            {
                FVector2 v = MathUtils.Mul(ref transform, Vertices[i]);
                lower = FVector2.Min(lower, v);
                upper = FVector2.Max(upper, v);
            }

            FVector2 r = new FVector2(Radius, Radius);

            aabb.LowerBound = lower - r;
            aabb.UpperBound = upper + r;
        }
Exemplo n.º 3
0
        /// <summary>
        /// Given a transform, compute the associated axis aligned bounding box for a child shape.
        /// </summary>
        /// <param name="aabb">The aabb results.</param>
        /// <param name="transform">The world transform of the shape.</param>
        /// <param name="childIndex">The child shape index.</param>
        public override void ComputeAABB(out AABB aabb, ref Transform transform, int childIndex)
        {
            Debug.Assert(childIndex < Vertices.Count);

            int i1 = childIndex;
            int i2 = childIndex + 1;

            if (i2 == Vertices.Count)
            {
                i2 = 0;
            }

            FVector2 v1 = MathUtils.Mul(ref transform, Vertices[i1]);
            FVector2 v2 = MathUtils.Mul(ref transform, Vertices[i2]);

            aabb.LowerBound = FVector2.Min(v1, v2);
            aabb.UpperBound = FVector2.Max(v1, v2);
        }
Exemplo n.º 4
0
    /// <summary>
    /// tests if ray intersects AABB
    /// </summary>
    /// <param name="aabb"></param>
    /// <returns></returns>
    public static bool RayCastAABB(AABB aabb, FVector2 p1, FVector2 p2)
    {
        AABB segmentAABB = new AABB();

        {
            FVector2.Min(ref p1, ref p2, out segmentAABB.LowerBound);
            FVector2.Max(ref p1, ref p2, out segmentAABB.UpperBound);
        }
        if (!AABB.TestOverlap(aabb, segmentAABB))
        {
            return(false);
        }

        FVector2 rayDir = p2 - p1;
        FVector2 rayPos = p1;

        FVector2 norm = new FVector2(-rayDir.Y, rayDir.X); //normal to ray

        if (norm.Length() == 0.0)
        {
            return(true); //if ray is just a point, return true (iff point is within aabb, as tested earlier)
        }
        norm.Normalize();

        float dPos = FVector2.Dot(rayPos, norm);

        FVector2[] verts = aabb.GetVertices();
        float      d0    = FVector2.Dot(verts[0], norm) - dPos;

        for (int i = 1; i < 4; i++)
        {
            float d = FVector2.Dot(verts[i], norm) - dPos;
            if (Math.Sign(d) != Math.Sign(d0))
            {
                //return true if the ray splits the vertices (ie: sign of dot products with normal are not all same)
                return(true);
            }
        }

        return(false);
    }
Exemplo n.º 5
0
 public static FVector2 Clamp(FVector2 a, FVector2 low, FVector2 high)
 {
     return(FVector2.Max(low, FVector2.Min(a, high)));
 }
Exemplo n.º 6
0
        /// <summary>
        /// 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.
        /// </summary>
        /// <param name="callback">A callback class that is called for each proxy that is hit by the ray.</param>
        /// <param name="input">The ray-cast input data. The ray extends from p1 to p1 + maxFraction * (p2 - p1).</param>
        public void RayCast(Func <RayCastInput, int, float> callback, ref RayCastInput input)
        {
            FVector2 p1 = input.Point1;
            FVector2 p2 = input.Point2;
            FVector2 r  = p2 - p1;

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

            // v is perpendicular to the segment.
            FVector2 absV = MathUtils.Abs(new FVector2(-r.Y, r.X));

            // 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();

            {
                FVector2 t = p1 + maxFraction * (p2 - p1);
                FVector2.Min(ref p1, ref t, out segmentAABB.LowerBound);
                FVector2.Max(ref p1, ref t, out segmentAABB.UpperBound);
            }

            _stack.Clear();
            _stack.Push(_root);

            while (_stack.Count > 0)
            {
                int nodeId = _stack.Pop();
                if (nodeId == NullNode)
                {
                    continue;
                }

                TreeNode <T> 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)
                FVector2 c          = node.AABB.Center;
                FVector2 h          = node.AABB.Extents;
                float    separation = Math.Abs(FVector2.Dot(new FVector2(-r.Y, r.X), p1 - c)) - FVector2.Dot(absV, h);
                if (separation > 0.0f)
                {
                    continue;
                }

                if (node.IsLeaf())
                {
                    RayCastInput subInput;
                    subInput.Point1      = input.Point1;
                    subInput.Point2      = input.Point2;
                    subInput.MaxFraction = maxFraction;

                    float value = callback(subInput, nodeId);

                    if (value == 0.0f)
                    {
                        // the client has terminated the raycast.
                        return;
                    }

                    if (value > 0.0f)
                    {
                        // Update segment bounding box.
                        maxFraction = value;
                        FVector2 t = p1 + maxFraction * (p2 - p1);
                        segmentAABB.LowerBound = FVector2.Min(p1, t);
                        segmentAABB.UpperBound = FVector2.Max(p1, t);
                    }
                }
                else
                {
                    _stack.Push(node.Child1);
                    _stack.Push(node.Child2);
                }
            }
        }