Exemplo n.º 1
0
        /// <inheritdoc/>
        public virtual IEnumerable <T> GetOverlaps(Ray ray)
        {
#if !POOL_ENUMERABLES
            Aabb rayAabb = new Aabb(ray.Origin, ray.Origin);
            rayAabb.Grow(ray.Origin + ray.Direction * ray.Length);

            var rayDirectionInverse = new Vector3F(
                1 / ray.Direction.X,
                1 / ray.Direction.Y,
                1 / ray.Direction.Z);

            float epsilon = Numeric.EpsilonF * (1 + Aabb.Extent.Length);

            foreach (var candidate in GetOverlaps(rayAabb))
            {
                if (GeometryHelper.HaveContact(GetAabbForItem(candidate), ray.Origin, rayDirectionInverse, ray.Length, epsilon))
                {
                    yield return(candidate);
                }
            }
#else
            // Avoiding garbage:
            return(GetOverlapsWithRayWork.Create(this, ref ray));
#endif
        }
Exemplo n.º 2
0
        /// <inheritdoc/>
        public IEnumerable <int> GetOverlaps(Ray ray)
        {
            Update(false);

#if !POOL_ENUMERABLES
            if (_numberOfItems == 0)
            {
                yield break;
            }

            var rayDirectionInverse = new Vector3F(
                1 / ray.Direction.X,
                1 / ray.Direction.Y,
                1 / ray.Direction.Z);

            float epsilon = Numeric.EpsilonF * (1 + Aabb.Extent.Length);

            // ----- Stackless traversal of tree:
            // The AABB tree nodes are stored in preorder traversal order. We can visit them in linear
            // order. The EscapeOffset of each node can be used to skip a subtree.
            int index = 0;
            while (index < _nodes.Length)
            {
                Node node        = _nodes[index];
                bool haveContact = GeometryHelper.HaveContact(GetAabb(node), ray.Origin, rayDirectionInverse, ray.Length, epsilon);

                if (haveContact && node.IsLeaf)
                {
                    yield return(node.Item);
                }

                if (haveContact || node.IsLeaf)
                {
                    // Given AABB intersects the internal AABB tree node or the node is a leaf.
                    // Continue with next item in preorder traversal order.
                    index++;
                }
                else
                {
                    // Given AABB does not touch the internal AABB tree node.
                    // --> Skip the subtree.
                    index += node.EscapeOffset;
                }
            }
#else
            // Avoiding garbage:
            return(GetOverlapsWithRayWork.Create(this, ref ray));
#endif
        }
Exemplo n.º 3
0
        /// <inheritdoc/>
        public override IEnumerable <T> GetOverlaps(Ray ray)
        {
            UpdateInternal();

#if !POOL_ENUMERABLES
            if (_root == null)
            {
                yield break;
            }

            var rayDirectionInverse = new Vector3F(
                1 / ray.Direction.X,
                1 / ray.Direction.Y,
                1 / ray.Direction.Z);

            float epsilon = Numeric.EpsilonF * (1 + Aabb.Extent.Length);

            var stack = DigitalRune.ResourcePools <Node> .Stacks.Obtain();

            stack.Push(_root);
            while (stack.Count > 0)
            {
                var node = stack.Pop();
                node.IsActive = true;

                if (GeometryHelper.HaveContact(node.Aabb, ray.Origin, rayDirectionInverse, ray.Length, epsilon))
                {
                    if (node.IsLeaf)
                    {
                        yield return(node.Item);
                    }
                    else
                    {
                        SplitIfNecessary(node);
                        stack.Push(node.RightChild);
                        stack.Push(node.LeftChild);
                    }
                }
            }

            DigitalRune.ResourcePools <Node> .Stacks.Recycle(stack);
#else
            // Avoiding garbage:
            return(GetOverlapsWithRayWork.Create(this, ref ray));
#endif
        }