private bool IsInsideMesh(Vector3 p, SpatialBinaryTree tree, Dictionary <Vector3, bool> pointInsideMeshCache)
    {
        bool isInsideMesh;

        if (pointInsideMeshCache.TryGetValue(Vector3.one, out isInsideMesh))
        {
            return(isInsideMesh);
        }

        var r = new Ray(p, new Vector3(1, 0, 0));
        var intersectionCount = tree.GetTris(r).Count(t => t.Intersect(r));
        var isInside          = intersectionCount % 2 != 0;

        pointInsideMeshCache[p] = isInside;
        return(isInside);
    }
    private IEnumerable <Box> CreateMeshIntersectingBoxes(GameObject colliderGo)
    {
        var       go                = colliderGo.transform.parent.gameObject;
        var       colliderLayer     = colliderGo.layer;
        LayerMask colliderLayerMask = 1 << colliderLayer;
        var       bounds            = CalculateLocalBounds(go);
        var       mesh              = colliderGo.GetComponent <MeshFilter>().sharedMesh;
        var       swTree            = Stopwatch.StartNew();
        var       tree              = new SpatialBinaryTree(mesh, spatialTreeLevelDepth);

        swTree.Stop();
        if (outputTimeMeasurements)
        {
            Debug.Log("SpatialTree Built in " + swTree.Elapsed);
        }

        var boxes = new Box[boxesPerEdge, boxesPerEdge, boxesPerEdge];
        var boxColliderPositions = new bool[boxesPerEdge, boxesPerEdge, boxesPerEdge];
        var s          = bounds.size / boxesPerEdge;
        var halfExtent = s / 2f;

        var directionsFromBoxCenterToCorners = new[]
        {
            new Vector3(1, 1, 1),
            new Vector3(1, 1, -1),
            new Vector3(1, -1, 1),
            new Vector3(1, -1, -1),
            new Vector3(-1, 1, 1),
            new Vector3(-1, 1, -1),
            new Vector3(-1, -1, 1),
            new Vector3(-1, -1, -1),
        };

        var pointInsideMeshCache = new Dictionary <Vector3, bool>();

        var sw = Stopwatch.StartNew();

        var colliders = new Collider[1000];

        for (var x = 0; x < boxesPerEdge; x++)
        {
            for (var y = 0; y < boxesPerEdge; y++)
            {
                for (var z = 0; z < boxesPerEdge; z++)
                {
                    var center = new Vector3(
                        bounds.center.x - bounds.size.x / 2 + s.x * x + halfExtent.x,
                        bounds.center.y - bounds.size.y / 2 + s.y * y + halfExtent.y,
                        bounds.center.z - bounds.size.z / 2 + s.z * z + halfExtent.z);

                    if (!avoidExceedingMesh)
                    {
                        if (avoidGapsInside)
                        {
                            var isInsideSurface = IsInsideMesh(center, tree, pointInsideMeshCache);
                            boxColliderPositions[x, y, z] = isInsideSurface;
                        }
                        else
                        {
                            var overlapsWithMeshSurface = Physics.OverlapBoxNonAlloc(center, halfExtent, colliders, Quaternion.identity, colliderLayerMask) > 0;
                            boxColliderPositions[x, y, z] = overlapsWithMeshSurface;
                        }
                        continue;
                    }

                    var allCornersInsideMesh =
                        (from d in directionsFromBoxCenterToCorners
                         select new Vector3(center.x + halfExtent.x * d.x, center.y + halfExtent.y * d.y, center.z + halfExtent.z * d.z))
                        .All(cornerPoint => IsInsideMesh(cornerPoint, tree, pointInsideMeshCache));
                    boxColliderPositions[x, y, z] = allCornersInsideMesh;
                }
            }
        }

        sw.Stop();
        if (outputTimeMeasurements)
        {
            Debug.Log("Boxes analyzed in " + sw.Elapsed);
        }

        for (var x = 0; x < boxesPerEdge; x++)
        {
            for (var y = 0; y < boxesPerEdge; y++)
            {
                for (var z = 0; z < boxesPerEdge; z++)
                {
                    if (!boxColliderPositions[x, y, z])
                    {
                        continue;
                    }
                    var center = new Vector3(
                        bounds.center.x - bounds.size.x / 2 + s.x * x + s.x / 2,
                        bounds.center.y - bounds.size.y / 2 + s.y * y + s.y / 2,
                        bounds.center.z - bounds.size.z / 2 + s.z * z + s.z / 2);
                    var b = new Box(boxes, center, s, new Vector3Int(x, y, z));
                    boxes[x, y, z] = b;
                    yield return(b);
                }
            }
        }
    }