PhysicsBlock GetNewPhysicsBlock(Block block, Vector3 blockWorldPosition, IndexPosition blockIPos, Chunk chunk)
        {
            if (unusedPhysBlocks.Count > 0)
            {
                PhysicsBlock b = unusedPhysBlocks.Dequeue() as PhysicsBlock;
                b.Block = block;
                b.Transform.Position = blockWorldPosition;
                b.BlockPos           = blockIPos;
                b.Chunk = chunk;

                return(b);
            }
            else
            {
                return(new PhysicsBlock(block, blockWorldPosition, blockIPos, chunk));
            }
        }
        public IEnumerable <PhysicsBodyComponent> GetBroadphaseIntersections(AxisAlignedBoundingBox broad)
        {
            _terrainBlockCache.Clear();

            // Convert the broad AABB to an IndexPosition AABB
            IndexPosition min = new IndexPosition(
                Maths.NegativeRound(broad.Min.X / Block.CUBE_SIZE),
                Maths.NegativeRound(broad.Min.Y / Block.CUBE_SIZE),
                Maths.NegativeRound(broad.Min.Z / Block.CUBE_SIZE));

            IndexPosition max = new IndexPosition(
                (int)Math.Ceiling(broad.Max.X / Block.CUBE_SIZE),
                (int)Math.Ceiling(broad.Max.Y / Block.CUBE_SIZE),
                (int)Math.Ceiling(broad.Max.Z / Block.CUBE_SIZE));

            // Calculate the chunk index to use as reference
            IndexPosition chunkIndex = Terrain.WorldToChunkCoords(broad.Center);

            // Try each block
            for (int x = min.X; x <= max.X; x++)
            {
                for (int y = min.Y; y <= max.Y; y++)
                {
                    for (int z = min.Z; z <= max.Z; z++)
                    {
                        // Calculate the index positions for the current block
                        IndexPosition blockIndexWorld = new IndexPosition(x, y, z);
                        IndexPosition blockChunkIndex = Chunk.BlockToChunkBlockCoords(chunkIndex, blockIndexWorld);

                        // Find the block
                        Chunk chunk;
                        int   fx, fy, fz;
                        Block block = Terrain.FindBlock(chunkIndex, blockChunkIndex.X, blockChunkIndex.Y, blockChunkIndex.Z,
                                                        out fx, out fy, out fz, out chunk);

                        // If this block has collision, process it
                        if (block.HasCollision())
                        {
                            IndexPosition blockIPos = new IndexPosition(fx, fy, fz);
                            // Calculate the blocks world position and create a PhyicsBlock from it
                            Vector3      blockWorldPosition = Chunk.ChunkBlockToWorldCoords(chunk.Position, blockIPos);
                            PhysicsBlock physBlock          = GetNewPhysicsBlock(block, blockWorldPosition, blockIPos, chunk);

                            // Grab its collider
                            PhysicsBodyComponent   physicsBody       = physBlock.GetComponent <PhysicsBodyComponent>();
                            AxisAlignedBoundingBox physBlockCollider = physicsBody.GetCollider();
                            //DebugAABBs.Add(physBlockCollider as AABoundingBox);

                            // Check if the block intersects the broad,
                            // if it does this block is valid for collision response
                            // TODO: Might be able to remove the intersect check
                            if (broad.Intersects(physBlockCollider))
                            {
                                _terrainBlockStorage.Add(physBlock);
                                _terrainBlockCache.Add(physicsBody);
                            }
                            else
                            {
                                unusedPhysBlocks.Enqueue(physBlock);
                            }
                        }
                    }
                }
            }

            return(_terrainBlockCache);
        }