Пример #1
0
            public void Execute(int i_arrayIndex)
            {
                Entity octreeRootNodeEntity = a_collisionChecksEntities [i_arrayIndex];


                // Its value should be 0, if no collision is detected.
                // And >= 1, if instance collision is detected, or there is more than one collision,
                // indicating number of collisions.
                IsCollidingData isCollidingData = a_isCollidingData [octreeRootNodeEntity];
                // Stores reference to detected colliding instance.
                DynamicBuffer <CollisionInstancesBufferElement> a_collisionInstancesBuffer = collisionInstancesBufferElement [octreeRootNodeEntity];


                isCollidingData.i_nearestInstanceCollisionIndex = 0;
                isCollidingData.f_nearestDistance = float.PositiveInfinity;

                isCollidingData.i_collisionsCount = 0;                // Reset colliding instances counter.


                RootNodeData octreeRootNodeData = a_octreeRootNodeData [octreeRootNodeEntity];

                DynamicBuffer <NodeBufferElement> a_nodesBuffer = nodeBufferElement [octreeRootNodeEntity];
                DynamicBuffer <NodeInstancesIndexBufferElement> a_nodeInstancesIndexBuffer = nodeInstancesIndexBufferElement [octreeRootNodeEntity];
                DynamicBuffer <NodeChildrenBufferElement>       a_nodeChildrenBuffer       = nodeChildrenBufferElement [octreeRootNodeEntity];
                DynamicBuffer <InstanceBufferElement>           a_instanceBuffer           = instanceBufferElement [octreeRootNodeEntity];


                BoundsEntityPair4CollisionData rayEntityPair4CollisionData = a_boundsEntityPair4CollisionData [octreeRootNodeEntity];

                // Ray entity pair, for collision checks

                Entity bounds2CheckEntity = rayEntityPair4CollisionData.bounds2CheckEntity;


                // Is target octree active
                if (a_isActiveTag.Exists(bounds2CheckEntity))
                {
                    BoundsData checkBounds = a_boundsData [bounds2CheckEntity];


                    // To even allow instances collision checks, octree must have at least one instance.
                    if (octreeRootNodeData.i_totalInstancesCountInTree > 0)
                    {
                        if (GetCollidingBoundsInstances_Common._GetNodeColliding(octreeRootNodeData, octreeRootNodeData.i_rootNodeIndex, checkBounds.bounds, ref a_collisionInstancesBuffer, ref isCollidingData, a_nodesBuffer, a_nodeChildrenBuffer, a_nodeInstancesIndexBuffer, a_instanceBuffer))
                        {
                            /*
                             * // Debug
                             * Debug.Log ( "Is colliding." ) ;
                             */
                        }
                    }
                }

                a_isCollidingData [octreeRootNodeEntity] = isCollidingData;  // Set back.
            }
Пример #2
0
            public void Execute(int i_arrayIndex)
            {
                Entity octreeRayEntity = a_collisionChecksEntities [i_arrayIndex];


                // Its value should be 0, if no collision is detected.
                // And >= 1, if instance collision is detected, or there is more than one collision,
                // indicating number of collisions.
                IsCollidingData isCollidingData = a_isCollidingData [octreeRayEntity];

                isCollidingData.i_collisionsCount = 0;                    // Reset colliding instances counter.
                // isCollidingData.i_nearestInstanceCollisionIndex  = 0 ; // Unused
                // isCollidingData.f_nearestDistance                = float.PositiveInfinity ; // Unused



                OctreeEntityPair4CollisionData octreeEntityPair4CollisionData = a_octreeEntityPair4CollisionData [octreeRayEntity];
                RayData            rayData            = a_rayData [octreeRayEntity];
                RayMaxDistanceData rayMaxDistanceData = a_rayMaxDistanceData [octreeRayEntity];


                // Octree entity pair, for collision checks

                Entity octreeRootNodeEntity = octreeEntityPair4CollisionData.octree2CheckEntity;

                // Is target octree active
                if (a_isActiveTag.Exists(octreeRootNodeEntity))
                {
                    RootNodeData octreeRootNodeData = a_octreeRootNodeData [octreeRootNodeEntity];

                    DynamicBuffer <NodeBufferElement> a_nodesBuffer = nodeBufferElement [octreeRootNodeEntity];
                    DynamicBuffer <NodeInstancesIndexBufferElement> a_nodeInstancesIndexBuffer = nodeInstancesIndexBufferElement [octreeRootNodeEntity];
                    DynamicBuffer <NodeChildrenBufferElement>       a_nodeChildrenBuffer       = nodeChildrenBufferElement [octreeRootNodeEntity];
                    DynamicBuffer <InstanceBufferElement>           a_instanceBuffer           = instanceBufferElement [octreeRootNodeEntity];



                    // To even allow instances collision checks, octree must have at least one instance.
                    if (octreeRootNodeData.i_totalInstancesCountInTree > 0)
                    {
                        if (IsRayColliding_Common._IsNodeColliding(octreeRootNodeData, octreeRootNodeData.i_rootNodeIndex, rayData.ray, ref isCollidingData, a_nodesBuffer, a_nodeChildrenBuffer, a_nodeInstancesIndexBuffer, a_instanceBuffer, rayMaxDistanceData.f))
                        {
                            /*
                             * // Debug
                             * Debug.Log ( "Is colliding." ) ;
                             */
                        }
                    }
                }

                a_isCollidingData [octreeRayEntity] = isCollidingData;  // Set back.
            }
        static public void _DebugRays(EntityArray a_collisionChecksEntities, ComponentDataFromEntity <RayData> a_rayData, ComponentDataFromEntity <RayMaxDistanceData> a_rayMaxDistanceData, ComponentDataFromEntity <IsCollidingData> a_isCollidingData, ComponentDataFromEntity <RayEntityPair4CollisionData> a_rayEntityPair4CollisionData, bool canDebugAllChecks, bool canDebugAllrays)
        {
            // Debug all, or only one check
            int i_debugCollisionChecksCount = canDebugAllChecks ? a_collisionChecksEntities.Length : 1;


            // Debug
            // ! Ensure test this only with single, or at most few ray entiities.
            for (int i_collisionChecksIndex = 0; i_collisionChecksIndex < i_debugCollisionChecksCount; i_collisionChecksIndex++)
            {
                Entity octreeRayEntity = a_collisionChecksEntities [i_collisionChecksIndex];
                Entity octreeRayEntity2;

                if (!a_rayData.Exists(octreeRayEntity))
                {
                    RayEntityPair4CollisionData rayEntityPair4CollisionData = a_rayEntityPair4CollisionData [octreeRayEntity];
                    octreeRayEntity2 = rayEntityPair4CollisionData.ray2CheckEntity;
                }
                else
                {
                    octreeRayEntity2 = octreeRayEntity;
                }

                // Draw all available rays, or signle ray
                if (canDebugAllrays)
                {
                    RayData            rayData            = a_rayData [octreeRayEntity2];
                    RayMaxDistanceData rayMaxDistanceData = a_rayMaxDistanceData [octreeRayEntity2];

                    Debug.DrawLine(rayData.ray.origin, rayData.ray.origin + rayData.ray.direction * rayMaxDistanceData.f, Color.red);
                }
                else if (i_collisionChecksIndex == 0)
                {
                    RayData            rayData            = a_rayData [octreeRayEntity2];
                    RayMaxDistanceData rayMaxDistanceData = a_rayMaxDistanceData [octreeRayEntity2];

                    Debug.DrawLine(rayData.ray.origin, rayData.ray.origin + rayData.ray.direction * rayMaxDistanceData.f, Color.red);
                }


                IsCollidingData isCollidingData = a_isCollidingData [octreeRayEntity];

                if (isCollidingData.i_collisionsCount > 0)
                {
                    Debug.Log("Is colliding.");
                }
            }
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="a_collisionChecksEntities"></param>
        /// <param name="a_isCollidingData"></param>
        /// <param name="collisionInstancesBufferElement"></param>
        /// <param name="canDebugAllChecks">Debug Log all checks, or only one (first one)</param>
        static public void _DebugBounds(EntityCommandBuffer ecb, EntityArray a_collisionChecksEntities, ComponentDataFromEntity <IsCollidingData> a_isCollidingData, BufferFromEntity <CollisionInstancesBufferElement> collisionInstancesBufferElement, bool canDebugAllChecks)
        {
            // Debug
            // ! Ensure test this only with single, or at most few ray entiities.


            // Debug all, or only one check
            int i_debugCollisionChecksCount = canDebugAllChecks ? a_collisionChecksEntities.Length : 1;

            for (int i_collisionChecksIndex = 0; i_collisionChecksIndex < i_debugCollisionChecksCount; i_collisionChecksIndex++)
            {
                Entity octreeRayEntity = a_collisionChecksEntities [i_collisionChecksIndex];

                // Last known instances collisions count.
                IsCollidingData isCollidingData = a_isCollidingData [octreeRayEntity];

                if (isCollidingData.i_collisionsCount > 0)
                {
                    // Debug.Log ( "Octree: Last known instances collisions count #" + isCollidingData.i_collisionsCount ) ;

                    // Stores reference to detected colliding instance.
                    DynamicBuffer <CollisionInstancesBufferElement> a_collisionInstancesBuffer = collisionInstancesBufferElement [octreeRayEntity];


                    string s_collidingIDs = "";

                    CollisionInstancesBufferElement collisionInstancesBuffer;

                    for (int i = 0; i < isCollidingData.i_collisionsCount; i++)
                    {
                        collisionInstancesBuffer = a_collisionInstancesBuffer [i];
                        s_collidingIDs          += collisionInstancesBuffer.i_ID + ", ";
                    }


                    // Test highlight
                    // Highlight.SwitchMethods._Switch ( ecb, closestInstanceEntity ) ;

                    Debug.Log("Is colliding with #" + isCollidingData.i_collisionsCount + " instances of IDs: " + s_collidingIDs);
                }
            } // for
        }
Пример #5
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="a_collisionChecksEntities"></param>
        /// <param name="a_isCollidingData"></param>
        /// <param name="canDebugAllChecks">Debug Log all checks, or only one (first one)</param>
        static public void _DebugBounds(EntityArray a_collisionChecksEntities, ComponentDataFromEntity <IsCollidingData> a_isCollidingData, bool canDebugAllChecks)
        {
            // Debug
            // ! Ensure test this only with single, or at most few ray entiities.


            // Debug all, or only one check
            int i_debugCollisionChecksCount = canDebugAllChecks ? a_collisionChecksEntities.Length : 1;

            for (int i_collisionChecksIndex = 0; i_collisionChecksIndex < i_debugCollisionChecksCount; i_collisionChecksIndex++)
            // for ( int i_collisionChecksIndex = 0; i_collisionChecksIndex < a_collisionChecksEntities.Length; i_collisionChecksIndex ++ )
            {
                Entity          octreeEntity    = a_collisionChecksEntities [i_collisionChecksIndex];
                IsCollidingData isCollidingData = a_isCollidingData [octreeEntity];

                if (isCollidingData.i_collisionsCount > 0)
                {
                    Debug.Log("Is colliding.");
                }
            }
        }
            public void Execute(int i_arrayIndex)
            {
                Entity octreeRootNodeEntity = a_collisionChecksEntities [i_arrayIndex];


                // Its value should be 0, if no collision is detected.
                // And >= 1, if instance collision is detected, or there is more than one collision,
                // indicating number of collisions.
                IsCollidingData isCollidingData = a_isCollidingData [octreeRootNodeEntity];
                // Stores reference to detected colliding instance.
                DynamicBuffer <CollisionInstancesBufferElement> a_collisionInstancesBuffer = collisionInstancesBufferElement [octreeRootNodeEntity];


                isCollidingData.i_nearestInstanceCollisionIndex = 0;
                isCollidingData.f_nearestDistance = float.PositiveInfinity;

                isCollidingData.i_collisionsCount = 0;                // Reset colliding instances counter.


                RootNodeData octreeRootNodeData = a_octreeRootNodeData [octreeRootNodeEntity];

                DynamicBuffer <NodeBufferElement> a_nodesBuffer = nodeBufferElement [octreeRootNodeEntity];
                DynamicBuffer <NodeInstancesIndexBufferElement> a_nodeInstancesIndexBuffer = nodeInstancesIndexBufferElement [octreeRootNodeEntity];
                DynamicBuffer <NodeChildrenBufferElement>       a_nodeChildrenBuffer       = nodeChildrenBufferElement [octreeRootNodeEntity];
                DynamicBuffer <InstanceBufferElement>           a_instanceBuffer           = instanceBufferElement [octreeRootNodeEntity];


                RayEntityPair4CollisionData rayEntityPair4CollisionData = a_rayEntityPair4CollisionData [octreeRootNodeEntity];

                // Ray entity pair, for collision checks

                Entity ray2CheckEntity = rayEntityPair4CollisionData.ray2CheckEntity;

                // Is target octree active
                if (a_isActiveTag.Exists(ray2CheckEntity))
                {
                    RayData            rayData            = a_rayData [ray2CheckEntity];
                    RayMaxDistanceData rayMaxDistanceData = a_rayMaxDistanceData [ray2CheckEntity];


                    // To even allow instances collision checks, octree must have at least one instance.
                    if (octreeRootNodeData.i_totalInstancesCountInTree > 0)
                    {
                        if (GetCollidingRayInstances_Common._GetNodeColliding(octreeRootNodeData, octreeRootNodeData.i_rootNodeIndex, rayData.ray, ref a_collisionInstancesBuffer, ref isCollidingData, a_nodesBuffer, a_nodeChildrenBuffer, a_nodeInstancesIndexBuffer, a_instanceBuffer, rayMaxDistanceData.f))
                        {
                            /*
                             * // Debug
                             * string s_collidingIDs = "" ;
                             * int i_collisionsCount = isCollidingData.i_collisionsCount ;
                             *
                             * for ( int i = 0; i < i_collisionsCount; i ++ )
                             * {
                             *  CollisionInstancesBufferElement collisionInstancesBuffer = a_collisionInstancesBuffer [i] ;
                             *  s_collidingIDs += collisionInstancesBuffer.i_ID + ", " ;
                             * }
                             *
                             * Debug.Log ( "Is colliding with #" + i_collisionsCount + " instances of IDs: " + s_collidingIDs + "; Nearest collided instance is at " + isCollidingData.f_nearestDistance + "m, with index #" + isCollidingData.i_nearestInstanceCollisionIndex ) ;
                             */
                        }
                    }
                }

                a_isCollidingData [octreeRootNodeEntity] = isCollidingData;  // Set back.
            }
        /// <summary>
        /// Returns an collection of instances, that intersect with the specified bounds, if any. Otherwise returns an empty array. See also: IsColliding.
        /// </summary>
        /// <param name="i_nodeIndex">Internal octree node index.</param>
        /// <param name="checkBounds">Bounds to check. Passing by ref as it improves performance with structs.</param>
        /// <param name="l_resultInstanceIDs">List result.</param>
        static public bool _GetNodeColliding(RootNodeData octreeRootNodeData, int i_nodeIndex, Bounds checkBounds, ref DynamicBuffer <CollisionInstancesBufferElement> a_collisionInstancesBuffer, ref IsCollidingData isCollidingData, DynamicBuffer <NodeBufferElement> a_nodesBuffer, DynamicBuffer <NodeChildrenBufferElement> a_nodeChildrenBuffer, DynamicBuffer <NodeInstancesIndexBufferElement> a_nodeInstancesIndexBuffer, DynamicBuffer <InstanceBufferElement> a_instanceBuffer)
        {
            // float f_distance ;
            CollisionInstancesBufferElement collisionInstancesBuffer = new CollisionInstancesBufferElement();

            NodeBufferElement nodeBuffer = a_nodesBuffer [i_nodeIndex];

            // Are the input bounds at least partially in this node?
            if (!nodeBuffer.bounds.Intersects(checkBounds))
            {
                return(isCollidingData.i_collisionsCount > 0 ? true : false);
            }


            if (nodeBuffer.i_instancesCount >= 0)
            {
                int i_nodeInstancesIndexOffset = i_nodeIndex * octreeRootNodeData.i_instancesAllowedCount;

                // Check against any objects in this node
                for (int i = 0; i < octreeRootNodeData.i_instancesAllowedCount; i++)
                {
                    NodeInstancesIndexBufferElement nodeInstancesIndexBuffer = a_nodeInstancesIndexBuffer [i_nodeInstancesIndexOffset + i];

                    // Get index of instance
                    int i_instanceIndex = nodeInstancesIndexBuffer.i;

                    // Check if instance exists, and if has intersecting bounds.
                    if (i_instanceIndex >= 0)
                    {
                        InstanceBufferElement instanceBuffer = a_instanceBuffer [i_instanceIndex];

                        // Check if instance exists, and if has intersecting bounds.
                        if (instanceBuffer.bounds.Intersects(checkBounds))
                        {
                            // l_resultInstanceIDs.Add ( instanceBuffer.i_ID ) ;

                            //if ( f_distance < isCollidingData.f_nearestDistance )
                            //{
                            //    isCollidingData.f_nearestDistance = f_distance ;
                            //    isCollidingData.i_nearestInstanceCollisionIndex = isCollidingData.i_collisionsCount ;
                            //}



                            // Is expected, that the required length is no greater than current length + 1
                            // And is not negative.
                            int i_collisionsCount = isCollidingData.i_collisionsCount;
                            collisionInstancesBuffer.i_ID      = instanceBuffer.i_ID;
                            collisionInstancesBuffer.i_version = instanceBuffer.i_entityVersion;  // Optional, used when Id is used as entity index

                            // Assign colliding instance ID to buffer.
                            if (a_collisionInstancesBuffer.Length <= i_collisionsCount)
                            {
                                // Expand buffer if needed
                                a_collisionInstancesBuffer.Add(collisionInstancesBuffer);
                            }
                            else
                            {
                                a_collisionInstancesBuffer [i_collisionsCount] = collisionInstancesBuffer;
                            }

                            isCollidingData.i_collisionsCount++;
                        }
                    }
                }
            }

            // Check children for collisions
            // Check if having children
            if (nodeBuffer.i_childrenCount > 0)
            {
                int i_nodeChildrenIndexOffset = i_nodeIndex * 8;

                // We checked that is having children.
                for (int i = 0; i < 8; i++)
                {
                    NodeChildrenBufferElement nodeChildrenBuffer = a_nodeChildrenBuffer [i_nodeChildrenIndexOffset + i];
                    int i_nodeChildIndex = nodeChildrenBuffer.i_nodesIndex;

                    // Check if node exists
                    if (i_nodeChildIndex >= 0)
                    {
                        _GetNodeColliding(octreeRootNodeData, i_nodeChildIndex, checkBounds, ref a_collisionInstancesBuffer, ref isCollidingData, a_nodesBuffer, a_nodeChildrenBuffer, a_nodeInstancesIndexBuffer, a_instanceBuffer);
                    }
                }
            }

            return(isCollidingData.i_collisionsCount > 0 ? true : false);
        }
Пример #8
0
        /// <summary>
        /// Check if the specified bounds intersect with anything in the tree. See also: GetColliding.
        /// </summary>
        /// <param name="i_nodeIndex">Internal octree node index.</param>
        /// <param name="checkBounds">Bounds to check.</param>
        /// <returns>True if there was a collision.</returns>
        static public bool _IsNodeColliding(RootNodeData rootNodeData, int i_nodeIndex, Bounds checkBounds, ref IsCollidingData isCollidingData, DynamicBuffer <NodeBufferElement> a_nodesBuffer, DynamicBuffer <NodeChildrenBufferElement> a_nodeChildrenBuffer, DynamicBuffer <NodeInstancesIndexBufferElement> a_nodeInstancesIndexBuffer, DynamicBuffer <InstanceBufferElement> a_instanceBuffer)
        {
            NodeBufferElement nodeBuffer = a_nodesBuffer [i_nodeIndex];

            // Are the input bounds at least partially in this node?
            if (!nodeBuffer.bounds.Intersects(checkBounds))
            {
                return(false);
            }


            if (nodeBuffer.i_instancesCount >= 0)
            {
                int i_nodeInstancesIndexOffset = i_nodeIndex * rootNodeData.i_instancesAllowedCount;

                // Check against any objects in this node
                for (int i = 0; i < rootNodeData.i_instancesAllowedCount; i++)
                {
                    NodeInstancesIndexBufferElement nodeInstancesIndexBuffer = a_nodeInstancesIndexBuffer [i_nodeInstancesIndexOffset + i];

                    // Get index of instance
                    int i_instanceIndex = nodeInstancesIndexBuffer.i;

                    // Check if instance exists, and if has intersecting bounds.
                    if (i_instanceIndex >= 0)
                    {
                        InstanceBufferElement instanceBuffer = a_instanceBuffer [i_instanceIndex];

                        // Check if instance exists, and if has intersecting bounds.
                        if (instanceBuffer.bounds.Intersects(checkBounds))
                        {
                            isCollidingData.i_collisionsCount = 1;
                            return(true);
                        }
                    }
                }
            }

            // Check children for collisions
            // Check if having children
            if (nodeBuffer.i_childrenCount > 0)
            {
                int i_nodeChildrenIndexOffset = i_nodeIndex * 8;

                // We checked that is having children.
                for (int i = 0; i < 8; i++)
                {
                    NodeChildrenBufferElement nodeChildrenBuffer = a_nodeChildrenBuffer [i_nodeChildrenIndexOffset + i];
                    int i_nodeChildIndex = nodeChildrenBuffer.i_nodesIndex;

                    // Check if node exists
                    if (i_nodeChildIndex >= 0)
                    {
                        if (_IsNodeColliding(rootNodeData, i_nodeChildIndex, checkBounds, ref isCollidingData, a_nodesBuffer, a_nodeChildrenBuffer, a_nodeInstancesIndexBuffer, a_instanceBuffer))
                        {
                            isCollidingData.i_collisionsCount = 1;
                            return(true);
                        }
                    }
                }
            }

            return(false);
        }
        /// <summary>
        /// Check if the specified ray intersects with anything in the tree. See also: GetColliding.
        /// </summary>
        /// <param name="i_nodeIndex">Internal octree node index.</param>
        /// <param name="checkRay">Ray to check.</param>
        /// <param name="f_maxDistance">Distance to check.</param>
        /// <returns>True if there was a collision.</returns>
        static public bool _IsNodeColliding(RootNodeData rootNodeData, int i_nodeIndex, Ray checkRay, ref IsCollidingData isCollidingData, DynamicBuffer <NodeBufferElement> a_nodesBuffer, DynamicBuffer <NodeChildrenBufferElement> a_nodeChildrenBuffer, DynamicBuffer <NodeInstancesIndexBufferElement> a_nodeInstancesIndexBuffer, DynamicBuffer <InstanceBufferElement> a_instanceBuffer, float f_maxDistance = float.PositiveInfinity)
        {
            // Is the input ray at least partially in this node?

            float f_distance;

            NodeBufferElement nodeBuffer = a_nodesBuffer [i_nodeIndex];

            if (!nodeBuffer.bounds.IntersectRay(checkRay, out f_distance) || f_distance > f_maxDistance)
            {
                return(false);
            }

            if (nodeBuffer.i_instancesCount >= 0)
            {
                int i_nodeInstancesIndexOffset = i_nodeIndex * rootNodeData.i_instancesAllowedCount;

                // Check against any objects in this node
                for (int i = 0; i < rootNodeData.i_instancesAllowedCount; i++)
                {
                    NodeInstancesIndexBufferElement nodeInstancesIndexBuffer = a_nodeInstancesIndexBuffer [i_nodeInstancesIndexOffset + i];

                    // Get index of instance
                    int i_instanceIndex = nodeInstancesIndexBuffer.i;

                    // Check if instance exists, and if has intersecting bounds.
                    if (i_instanceIndex >= 0)
                    {
                        InstanceBufferElement instanceBuffer = a_instanceBuffer [i_instanceIndex];

                        if (instanceBuffer.bounds.IntersectRay(checkRay, out f_distance) && f_distance <= f_maxDistance)
                        {
                            isCollidingData.i_collisionsCount = 1;  // Is colliding
                            return(true);
                        }
                    }
                }
            }

            // Check children for collisions
            // Check if having children
            if (nodeBuffer.i_childrenCount > 0)
            {
                int i_nodeChildrenIndexOffset = i_nodeIndex * 8;

                // We checked that is having children.
                for (int i = 0; i < 8; i++)
                {
                    NodeChildrenBufferElement nodeChildrenBuffer = a_nodeChildrenBuffer [i_nodeChildrenIndexOffset + i];
                    int i_nodeChildIndex = nodeChildrenBuffer.i_nodesIndex;

                    // Check if node exists
                    if (i_nodeChildIndex >= 0)
                    {
                        if (_IsNodeColliding(rootNodeData, i_nodeChildIndex, checkRay, ref isCollidingData, a_nodesBuffer, a_nodeChildrenBuffer, a_nodeInstancesIndexBuffer, a_instanceBuffer, f_maxDistance))
                        {
                            isCollidingData.i_collisionsCount = 1;  // Is colliding
                            return(true);
                        }
                    }
                }
            }

            return(false);
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="a_collisionChecksEntities"></param>
        /// <param name="a_rayData"></param>
        /// <param name="a_rayMaxDistanceData"></param>
        /// <param name="a_isCollidingData"></param>
        /// <param name="collisionInstancesBufferElement"></param>
        /// <param name="canDebugAllChecks">Debug Log all checks, or only one (first one)</param>
        /// <param name="canDebugAllrays">Draw all, or only single ray (first one).</param>
        static public void _DebugRays(EntityCommandBuffer ecb, EntityArray a_collisionChecksEntities, ComponentDataFromEntity <RayData> a_rayData, ComponentDataFromEntity <RayMaxDistanceData> a_rayMaxDistanceData, ComponentDataFromEntity <IsCollidingData> a_isCollidingData, BufferFromEntity <CollisionInstancesBufferElement> collisionInstancesBufferElement, ComponentDataFromEntity <RayEntityPair4CollisionData> a_rayEntityPair4CollisionData, bool canDebugAllChecks, bool canDebugAllrays)
        {
            // Debug
            // ! Ensure test this only with single, or at most few ray entiities.


            // if ( !canDebugAllrays )

            // Debug all, or only one check
            int i_debugCollisionChecksCount = canDebugAllChecks ? a_collisionChecksEntities.Length : 1;

            for (int i_collisionChecksIndex = 0; i_collisionChecksIndex < i_debugCollisionChecksCount; i_collisionChecksIndex++)
            {
                Entity octreeRayEntity = a_collisionChecksEntities [i_collisionChecksIndex];
                Entity octreeRayEntity2;

                if (!a_rayData.Exists(octreeRayEntity))
                {
                    RayEntityPair4CollisionData rayEntityPair4CollisionData = a_rayEntityPair4CollisionData [octreeRayEntity];
                    octreeRayEntity2 = rayEntityPair4CollisionData.ray2CheckEntity;
                }
                else
                {
                    octreeRayEntity2 = octreeRayEntity;
                }

                // Draw all available rays, or signle ray
                if (canDebugAllrays)
                {
                    RayData            rayData            = a_rayData [octreeRayEntity2];
                    RayMaxDistanceData rayMaxDistanceData = a_rayMaxDistanceData [octreeRayEntity2];

                    Debug.DrawLine(rayData.ray.origin, rayData.ray.origin + rayData.ray.direction * rayMaxDistanceData.f, Color.red);
                }
                else if (i_collisionChecksIndex == 0)
                {
                    RayData            rayData            = a_rayData [octreeRayEntity2];
                    RayMaxDistanceData rayMaxDistanceData = a_rayMaxDistanceData [octreeRayEntity2];

                    Debug.DrawLine(rayData.ray.origin, rayData.ray.origin + rayData.ray.direction * rayMaxDistanceData.f, Color.red);
                }
                //}


                // Last known instances collisions count.
                IsCollidingData isCollidingData = a_isCollidingData [octreeRayEntity];

                if (isCollidingData.i_collisionsCount > 0)
                {
                    // Debug.Log ( "Octree: Last known instances collisions count #" + isCollidingData.i_collisionsCount ) ;

                    // Stores reference to detected colliding instance.
                    DynamicBuffer <CollisionInstancesBufferElement> a_collisionInstancesBuffer = collisionInstancesBufferElement [octreeRayEntity];


                    string s_collidingIDs = "";

                    CollisionInstancesBufferElement collisionInstancesBuffer;

                    for (int i = 0; i < isCollidingData.i_collisionsCount; i++)
                    {
                        collisionInstancesBuffer = a_collisionInstancesBuffer [i];
                        s_collidingIDs          += collisionInstancesBuffer.i_ID + ", ";
                    }

                    CollisionInstancesBufferElement closestCollisionInstance = a_collisionInstancesBuffer [isCollidingData.i_nearestInstanceCollisionIndex];
                    Entity closestInstanceEntity = new Entity()
                    {
                        Index   = closestCollisionInstance.i_ID,
                        Version = closestCollisionInstance.i_version
                    };

                    // Test highlight
                    Highlight.SwitchMethods._Switch(ecb, closestInstanceEntity);

                    Debug.Log("Is colliding with #" + isCollidingData.i_collisionsCount + " instances of IDs: " + s_collidingIDs + "; Nearest collided instance is at " + isCollidingData.f_nearestDistance + "m, with ID #" + a_collisionInstancesBuffer [isCollidingData.i_nearestInstanceCollisionIndex].i_ID);
                }
            } // for
        }
        /// <summary>
        /// Returns an array of objects that intersect with the specified ray, if any. Otherwise returns an empty array. See also: IsColliding.
        /// </summary>
        /// <param name="i_nodeIndex">Internal octree node index.</param>
        /// <param name="checkRay">Ray to check. Passing by ref as it improves performance with structs.</param>
        /// <param name="l_resultInstanceIDs">List result.</param>
        /// <param name="i_nearestIndex">Nerest collision index from the lits.</param>
        /// <param name="f_nearestDistance">Nerest collision distance.</param>
        /// <param name="maxDistance">Distance to check.</param>
        /// <returns>Instances index, that intersect with the specified ray.</returns>
        static public bool _GetNodeColliding(RootNodeData rootNodeData, int i_nodeIndex, Ray checkRay, ref DynamicBuffer <CollisionInstancesBufferElement> a_collisionInstancesBuffer, ref IsCollidingData isCollidingData, DynamicBuffer <NodeBufferElement> a_nodesBuffer, DynamicBuffer <NodeChildrenBufferElement> a_nodeChildrenBuffer, DynamicBuffer <NodeInstancesIndexBufferElement> a_nodeInstancesIndexBuffer, DynamicBuffer <InstanceBufferElement> a_instanceBuffer, float f_maxDistance = float.PositiveInfinity)
        {
            float f_distance;

            NodeBufferElement nodeBuffer = a_nodesBuffer [i_nodeIndex];

            if (!nodeBuffer.bounds.IntersectRay(checkRay, out f_distance) || f_distance > f_maxDistance)
            {
                return(isCollidingData.i_collisionsCount > 0 ? true : false);
            }

            if (nodeBuffer.i_instancesCount > 0)
            {
                int i_nodeInstancesIndexOffset = i_nodeIndex * rootNodeData.i_instancesAllowedCount;

                CollisionInstancesBufferElement collisionInstancesBuffer = new CollisionInstancesBufferElement();

                // Check against any objects in this node
                for (int i = 0; i < rootNodeData.i_instancesAllowedCount; i++)
                {
                    NodeInstancesIndexBufferElement nodeInstancesIndexBuffer = a_nodeInstancesIndexBuffer [i_nodeInstancesIndexOffset + i];

                    // Get index of instance
                    int i_instanceIndex = nodeInstancesIndexBuffer.i;

                    // Check if instance exists, and if has intersecting bounds.
                    if (i_instanceIndex >= 0)
                    {
                        InstanceBufferElement instanceBuffer = a_instanceBuffer [i_instanceIndex];


                        if (instanceBuffer.bounds.IntersectRay(checkRay, out f_distance) && f_distance <= f_maxDistance)
                        {
                            if (f_distance < isCollidingData.f_nearestDistance)
                            {
                                isCollidingData.f_nearestDistance = f_distance;
                                isCollidingData.i_nearestInstanceCollisionIndex = isCollidingData.i_collisionsCount;
                            }


                            // Is expected, that the required length is no greater than current length + 1
                            // And is not negative.
                            int i_collisionsCount = isCollidingData.i_collisionsCount;
                            collisionInstancesBuffer.i_ID      = instanceBuffer.i_ID;
                            collisionInstancesBuffer.i_version = instanceBuffer.i_entityVersion;  // Optional, used when Id is used as entity index

                            // Assign colliding instance ID to buffer.
                            if (a_collisionInstancesBuffer.Length <= i_collisionsCount)
                            {
                                // Expand buffer if needed
                                a_collisionInstancesBuffer.Add(collisionInstancesBuffer);
                            }
                            else
                            {
                                a_collisionInstancesBuffer [i_collisionsCount] = collisionInstancesBuffer;
                            }

                            isCollidingData.i_collisionsCount++;
                        }
                    }
                }
            }


            // Check children for collisions
            // Check if having children
            if (nodeBuffer.i_childrenCount > 0)
            {
                int i_nodeChildrenIndexOffset = i_nodeIndex * 8;

                // We checked that is having children.
                for (int i = 0; i < 8; i++)
                {
                    NodeChildrenBufferElement nodeChildrenBuffer = a_nodeChildrenBuffer [i_nodeChildrenIndexOffset + i];
                    int i_nodeChildIndex = nodeChildrenBuffer.i_nodesIndex;

                    // Check if node exists
                    if (i_nodeChildIndex >= 0)
                    {
                        _GetNodeColliding(rootNodeData, i_nodeChildIndex, checkRay, ref a_collisionInstancesBuffer, ref isCollidingData, a_nodesBuffer, a_nodeChildrenBuffer, a_nodeInstancesIndexBuffer, a_instanceBuffer, f_maxDistance);
                    }
                }
            }

            return(isCollidingData.i_collisionsCount > 0 ? true : false);
        }