Home > Mobile >  0-1 scaling on 3d sphere with raycast in unity
0-1 scaling on 3d sphere with raycast in unity

Time:03-26

I am shooting a raycast on a 3d sphere and i want a method which can get a float number between 0 (center of spehere) to 1 (circumference or outline of sphere) depending upon the raycasthit point (position). How can i achieve this.

I have tried calculating diffrence between the position of sphere and raycast impact point, it works somewhat but is very complex to implement in code.

Is there any other way of doing this or am i missing some math functions or vector functions which can help in this case.

CodePudding user response:

You could take a enter image description here

public class Example : MonoBehaviour
{
    public Camera mainCamera;

    private float result;
    private Ray ray;
    private Vector3 hitPoint;
    private Vector3? hitObjectCenter;
    private Vector3 planeHitPoint;

    private void Awake()
    {
        if (!mainCamera) mainCamera = Camera.main;
    }

    private void Update()
    {
        ray = mainCamera.ScreenPointToRay(Input.mousePosition);

        if (Physics.Raycast(ray, out var hit) && hit.collider is SphereCollider hitSphere)
        {
            hitPoint = hit.point;

            // This is assuming that your sphere is actually a sphere with uniform local scales
            var sphereRadius = hitSphere.radius * hitSphere.transform.lossyScale.x;

            hitObjectCenter = hit.collider.bounds.center;
            var plane = new Plane(-ray.direction, hitObjectCenter.Value);
            if(plane.Raycast(ray, out var hitDistance))
            {
                var planeHitPoint = ray.GetPoint(hitDistance);

                var result = Vector3.Distance(hitObjectCenter, planeHitPoint) / sphereRadius;
            }
        }
        else
        {
            hitObjectCenter = null;
        }
    }

    private Mesh planeMesh;

    private void OnDrawGizmos()
    {
        // if not hitting a sphere do nothing
        if (!hitObjectCenter.HasValue)
        {
            return;
        }

        // lazy initialize plan visualization
        if (!planeMesh)
        {
            planeMesh = new Mesh
            {
                vertices = new Vector3[4]
                {
                    new Vector3(-1, -1),
                    new Vector3(-1, 1),
                    new Vector3(1, 1),
                    new Vector3(1, -1)
                },
                triangles = new[]
                {
                    0, 1, 2,
                    0, 2, 3,

                    // backfaces
                    0, 2, 1,
                    0, 3, 2
                },
                normals = new Vector3[4]
                {
                    Vector3.forward,
                    Vector3.forward,
                    Vector3.forward,
                    Vector3.forward,
                }
            };
        }

        // Visualize ray
        Gizmos.color = Color.green;
        Gizmos.DrawLine(ray.origin, hitPoint);

        // Visualize hit point on sphere
        Gizmos.DrawWireSphere(hitPoint, 0.05f);

        // Visualize Plane
        Gizmos.color = Color.cyan;
        Gizmos.DrawWireMesh(planeMesh, hitObjectCenter.Value, Quaternion.LookRotation(ray.direction));

        // visualize hit point on plane
        Gizmos.DrawWireSphere(planeHitPoint, 0.05f);

        // Visualize distance
        Gizmos.color = Color.red;
        Gizmos.DrawLine(planeHitPoint, hitObjectCenter.Value);

        // print result on screen
        Handles.Label((planeHitPoint   hitObjectCenter.Value) / 2f, $"RESULT: {result:0.000}", new GUIStyle(EditorStyles.boldLabel) { alignment = TextAnchor.MiddleCenter });
    }
}
  • Related