public override bool Intersect(Ray ray)
        {
            float rayT = 0, t = 0;

            if (_bbox.Inside(ray.PointAtTime(ray.Start)))
            {
                rayT = ray.Start;
            }
            else if (!_bbox.IntersectP(ray, ref rayT, ref t))
            {
                return(false);
            }
            var gridIntersect = ray.PointAtTime(rayT);

            float[] nextCrossingT = new float[3], deltaT = new float[3];
            int[]   step          = new int[3], _out = new int[3], pos = new int[3];

            pos[0] = PosToVoxel(gridIntersect, 0);
            pos[1] = PosToVoxel(gridIntersect, 1);
            pos[2] = PosToVoxel(gridIntersect, 2);
            if (ray.Direction.X >= 0)
            {
                nextCrossingT[0] = rayT + (VoxelToPos(pos[0] + 1, 0) - gridIntersect.X) / ray.Direction.X;
                deltaT[0]        = _width[0] / ray.Direction.X;
                step[0]          = 1;
                _out[0]          = _nVoxels[0];
            }
            else
            {
                nextCrossingT[0] = rayT + (VoxelToPos(pos[0], 0) - gridIntersect.X) / ray.Direction.X;
                deltaT[0]        = -_width[0] / ray.Direction.X;
                step[0]          = -1;
                _out[0]          = -1;
            }

            if (ray.Direction.Y >= 0)
            {
                nextCrossingT[1] = rayT + (VoxelToPos(pos[1] + 1, 1) - gridIntersect.Y) / ray.Direction.Y;
                deltaT[1]        = _width[1] / ray.Direction.Y;
                step[1]          = 1;
                _out[1]          = _nVoxels[1];
            }
            else
            {
                nextCrossingT[1] = rayT + (VoxelToPos(pos[1], 1) - gridIntersect.Y) / ray.Direction.Y;
                deltaT[1]        = -_width[1] / ray.Direction.Y;
                step[1]          = -1;
                _out[1]          = -1;
            }

            if (ray.Direction.Z >= 0)
            {
                nextCrossingT[2] = rayT + (VoxelToPos(pos[2] + 1, 2) - gridIntersect.Z) / ray.Direction.Z;
                deltaT[2]        = _width[2] / ray.Direction.Z;
                step[2]          = 1;
                _out[2]          = _nVoxels[2];
            }
            else
            {
                nextCrossingT[2] = rayT + (VoxelToPos(pos[2], 2) - gridIntersect.Z) / ray.Direction.Z;
                deltaT[2]        = -_width[2] / ray.Direction.Z;
                step[2]          = -1;
                _out[2]          = -1;
            }

            for (; ;)
            {
                var voxel = _voxels[Offset(pos[0], pos[1], pos[2])];
                if (voxel != null)
                {
                    if (voxel.Intersect(ray))
                    {
                        return(true);
                    }
                }
                var bits = (((nextCrossingT[0] < nextCrossingT[1]) ? 1 : 0) << 2) +
                           (((nextCrossingT[0] < nextCrossingT[2]) ? 1 : 0) << 1) +
                           (((nextCrossingT[1] < nextCrossingT[2]) ? 1 : 0));
                var stepAxis = _cmpToAxis[bits];
                if (ray.End < nextCrossingT[stepAxis])
                {
                    break;
                }
                pos[stepAxis] += step[stepAxis];
                if (pos[stepAxis] == _out[stepAxis])
                {
                    break;
                }
                nextCrossingT[stepAxis] += deltaT[stepAxis];
            }
            return(false);
        }
        public override bool Intersect(Ray ray)
        {
            float rayT = 0, t = 0;

            if (_bbox.Inside(ray.PointAtTime(ray.Start)))
            {
                rayT = ray.Start;
            }
            else if (!_bbox.IntersectP(ray, ref rayT, ref t))
            {
                return(false);
            }
            var gridIntersect = ray.PointAtTime(rayT);

            float[] nextCrossingT = new float[3], deltaT = new float[3];
            int[]   step          = new int[3], _out = new int[3], pos = new int[3];

            for (var i = 0; i < 3; i++)
            {
                pos[i] = PosToVoxel(gridIntersect, i);
                if (ray.Direction[i] >= 0)
                {
                    nextCrossingT[i] = rayT + (VoxelToPos(pos[i] + 1, i) - gridIntersect[i]) / ray.Direction[i];
                    deltaT[i]        = _width[i] / ray.Direction[i];
                    step[i]          = 1;
                    _out[i]          = _nVoxels[i];
                }
                else
                {
                    nextCrossingT[i] = rayT + (VoxelToPos(pos[i], i) - gridIntersect[i]) / ray.Direction[i];
                    deltaT[i]        = -_width[i] / ray.Direction[i];
                    step[i]          = -1;
                    _out[i]          = -1;
                }
            }

            for (;;)
            {
                var voxel = _voxels[Offset(pos[0], pos[1], pos[2])];
                if (voxel != null)
                {
                    if (voxel.Intersect(ray))
                    {
                        return(true);
                    }
                }
                var bits = (((nextCrossingT[0] < nextCrossingT[1]) ? 1 : 0) << 2) +
                           (((nextCrossingT[0] < nextCrossingT[2]) ? 1 : 0) << 1) +
                           (((nextCrossingT[1] < nextCrossingT[2]) ? 1 : 0));
                var stepAxis = _cmpToAxis[bits];
                if (ray.End < nextCrossingT[stepAxis])
                {
                    break;
                }
                pos[stepAxis] += step[stepAxis];
                if (pos[stepAxis] == _out[stepAxis])
                {
                    break;
                }
                nextCrossingT[stepAxis] += deltaT[stepAxis];
            }
            return(false);
        }