Ejemplo n.º 1
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(b2BroadphaseRayCastCallback callback, b2RayCastInput input)
    {
        b2Vec2 p1 = new b2Vec2(input.p1);
        b2Vec2 p2 = new b2Vec2(input.p2);
        b2Vec2 r  = p2 - p1;

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

        // v is perpendicular to the segment.
        b2Vec2 v     = Utils.b2Cross(1.0f, r);
        b2Vec2 abs_v = Utils.b2Abs(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.
        b2AABB segmentAABB = new b2AABB();
        {
            b2Vec2 t = p1 + maxFraction * (p2 - p1);
            segmentAABB.lowerBound = Utils.b2Min(p1, t);
            segmentAABB.upperBound = Utils.b2Max(p1, t);
        }

        Stack <int> stack = new Stack <int>(256);

        stack.Push(m_root);

        while (stack.Count > 0)
        {
            int nodeId = stack.Pop();
            if (nodeId == Settings.b2_nullNode)
            {
                continue;
            }

            b2TreeNode node = m_nodes[nodeId];

            if (Utils.b2TestOverlap(ref node.aabb, ref segmentAABB) == false)
            {
                continue;
            }

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

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

                float value = callback(subInput, nodeId);

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

                if (value > 0.0f)
                {
                    // Update segment bounding box.
                    maxFraction = value;
                    b2Vec2 t = p1 + maxFraction * (p2 - p1);
                    segmentAABB.lowerBound = Utils.b2Min(p1, t);
                    segmentAABB.upperBound = Utils.b2Max(p1, t);
                }
            }
            else
            {
                stack.Push(node.child1);
                stack.Push(node.child2);
            }
        }
    }
Ejemplo n.º 2
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(b2BroadphaseRayCastCallback callback, b2RayCastInput input)
 {
     m_tree.RayCast(callback, input);
 }