private void FindPlacementPlane()

in Assets/MRTK/SDK/Features/Utilities/Solvers/SurfaceMagnetism.cs [581:771]


        private void FindPlacementPlane(Vector3 origin, Vector3 direction, Vector3[] positions, Vector3[] normals, bool[] hits, float assetWidth, float maxNormalVariance, bool constrainVertical, bool useClosestDistance, out Plane plane, out float closestDistance)
        {
            int rayCount = positions.Length;

            Vector3 originalDirection = direction;

            if (constrainVertical)
            {
                direction.y = 0.0f;
                direction = direction.normalized;
            }

            // Go through all the points and find the closest distance
            closestDistance = float.PositiveInfinity;

            int numHits = 0;
            int closestPointIdx = -1;
            float farthestDistance = 0f;
            var averageNormal = Vector3.zero;

            for (int hitIndex = 0; hitIndex < rayCount; hitIndex++)
            {
                if (hits[hitIndex])
                {
                    float distance = Vector3.Dot(direction, positions[hitIndex] - origin);

                    if (distance < closestDistance)
                    {
                        closestPointIdx = hitIndex;
                        closestDistance = distance;
                    }

                    if (distance > farthestDistance)
                    {
                        farthestDistance = distance;
                    }

                    averageNormal += normals[hitIndex];
                    ++numHits;
                }
            }

            Vector3 closestPoint = positions[closestPointIdx];
            averageNormal /= numHits;

            // Calculate variance of all normals
            float variance = 0;

            for (int hitIndex = 0; hitIndex < rayCount; ++hitIndex)
            {
                if (hits[hitIndex])
                {
                    variance += (normals[hitIndex] - averageNormal).magnitude;
                }
            }

            variance /= numHits;

            // If variance is too high, I really don't want to deal with this surface
            // And if we don't even have enough rays, I'm not confident about this at all
            if (variance > maxNormalVariance || numHits < rayCount * 0.25f)
            {
                plane = new Plane(-direction, closestPoint);
                return;
            }

            // go through all the points and find the most orthogonal plane
            var lowAngle = float.PositiveInfinity;
            var highAngle = float.NegativeInfinity;
            int lowIndex = -1;
            int highIndex = -1;

            for (int hitIndex = 0; hitIndex < rayCount; hitIndex++)
            {
                if (hits[hitIndex] == false || hitIndex == closestPointIdx)
                {
                    continue;
                }

                Vector3 difference = positions[hitIndex] - closestPoint;

                if (constrainVertical)
                {
                    difference.y = 0.0f;
                    difference.Normalize();

                    if (difference == Vector3.zero)
                    {
                        continue;
                    }
                }

                difference.Normalize();

                float angle = Vector3.Dot(direction, difference);

                if (angle < lowAngle)
                {
                    lowAngle = angle;
                    lowIndex = hitIndex;
                }
            }

            if (!constrainVertical && lowIndex != -1)
            {
                for (int hitIndex = 0; hitIndex < rayCount; hitIndex++)
                {
                    if (hits[hitIndex] == false || hitIndex == closestPointIdx || hitIndex == lowIndex)
                    {
                        continue;
                    }

                    float dot = Mathf.Abs(Vector3.Dot((positions[hitIndex] - closestPoint).normalized, (positions[lowIndex] - closestPoint).normalized));

                    if (dot > MaxDot)
                    {
                        continue;
                    }

                    float nextAngle = Mathf.Abs(Vector3.Dot(direction, Vector3.Cross(positions[lowIndex] - closestPoint, positions[hitIndex] - closestPoint).normalized));

                    if (nextAngle > highAngle)
                    {
                        highAngle = nextAngle;
                        highIndex = hitIndex;
                    }
                }
            }

            Vector3 placementNormal;

            if (lowIndex != -1)
            {
                if (debugEnabled)
                {
                    Debug.DrawLine(closestPoint, positions[lowIndex], Color.red);
                }

                if (highIndex != -1)
                {
                    if (debugEnabled)
                    {
                        Debug.DrawLine(closestPoint, positions[highIndex], Color.green);
                    }

                    placementNormal = Vector3.Cross(positions[lowIndex] - closestPoint, positions[highIndex] - closestPoint).normalized;
                }
                else
                {
                    Vector3 planeUp = Vector3.Cross(positions[lowIndex] - closestPoint, direction);
                    placementNormal = Vector3.Cross(positions[lowIndex] - closestPoint, constrainVertical ? Vector3.up : planeUp).normalized;
                }

                if (debugEnabled)
                {
                    Debug.DrawLine(closestPoint, closestPoint + placementNormal, Color.blue);
                }
            }
            else
            {
                placementNormal = direction * -1.0f;
            }

            if (Vector3.Dot(placementNormal, direction) > 0.0f)
            {
                placementNormal *= -1.0f;
            }

            plane = new Plane(placementNormal, closestPoint);

            if (debugEnabled)
            {
                Debug.DrawRay(closestPoint, placementNormal, Color.cyan);
            }

            // Figure out how far the plane should be.
            if (!useClosestDistance && closestPointIdx >= 0)
            {
                float centerPlaneDistance;

                if (plane.Raycast(new Ray(origin, originalDirection), out centerPlaneDistance) || !centerPlaneDistance.Equals(0.0f))
                {
                    // When the plane is nearly parallel to the user, we need to clamp the distance to where the raycasts hit.
                    closestDistance = Mathf.Clamp(centerPlaneDistance, closestDistance, farthestDistance + assetWidth * 0.5f);
                }
                else
                {
                    Debug.LogError("FindPlacementPlane: Not expected to have the center point not intersect the plane.");
                }
            }
        }