Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Voting for the Unity Awards are OPEN! We’re looking to celebrate creators across games, industry, film, and many more categories. Cast your vote now for all categories
    Dismiss Notice
  3. Dismiss Notice

Determining length of path of ray in object?

Discussion in 'Physics' started by Kobus, May 4, 2018.

  1. Kobus

    Kobus

    Joined:
    Mar 27, 2015
    Posts:
    48
    I would like to find out if there is a better or more efficient way of determining the length of the path that a ray travels through objects.

    For an algorithm I am working on I need to determine the length of the path that the Ray takes through an object (the red line segments in the mage below).

    upload_2018-5-4_6-45-49.png

    I am using Physics.RaycastAll because I need to process information for all objects the ray passes through. It looks like Raycasting only gives information when it enters a collider and not information about exiting the object.

    What I am currently doing is when the ray detects an object:
    • I get the primary hitpoint (where the ray made contact with the object)
    • I calculate a point on the ray a certain distance from the primary hitpoint in the forward direction along the ray.
    • Then create a second ray from that new point and do a raycastall in the reverse direction along the original ray up to the primary hitpoint.
    • This gives me secondary hitpoints.
    • When the primary and secondary hitpoints are on the same object, I calculate the distance between these two points.
    upload_2018-5-4_6-50-9.png

    I am hoping that there is a more efficient way of doing this, because this is all done for a square area of varying dimensions.
    upload_2018-5-4_7-2-18.png
    Can anyone help me to improve on this approach?

    I have included the code snippet. I have removed the unnecessary code as far as possible to reduce clutter.

    Code (CSharp):
    1.     private void Test()
    2.     {
    3.         Vector3 targetPoint;
    4.         float targetX = areaMinX;
    5.         float targetY = yLevel;    
    6.         float targetZ = areaMinZ;
    7.         RaycastHit[] hitInfos;
    8.         RaycastHit[] hitInfosReverse;
    9.         Ray rayMain;
    10.         Ray rayOpposing;
    11.  
    12.         List<Transform> sameObjectsList = new List<Transform>();
    13.         float minDistance = reverseRayDistance;
    14.         Vector3 beamVector = Vector3.zero;
    15.         Vector3 reverseVector = Vector3.zero;
    16.         Vector3 reversePoint = Vector3.zero;
    17.  
    18.         for (int index1 = 0; index1 < calcSizeVertical; index1++)
    19.         {
    20.             targetX = areaMinX;
    21.  
    22.             for (int index2 = 0; index2 < calcSizeHorizontal; index2++)
    23.             {
    24.                 minDistance = reverseRayDistance;
    25.                 targetPoint = new Vector3(targetX, targetY, targetZ);
    26.                 beamVector = targetPoint - originObject.transform.position;
    27.                 rayMain = new Ray(originObject.transform.position, beamVector);
    28.                 hitInfos = Physics.RaycastAll(rayMain, rayDistance);
    29.  
    30.                 for (int hitIndex = 0; hitIndex < hitInfos.Length; hitIndex++)
    31.                 {
    32.                     sameObjectsList.Clear();
    33.                     reverseVector = Vector3.Normalize(beamVector);
    34.                     reversePoint = hitInfos[hitIndex].point + (reverseVector * reverseRayDistance);
    35.  
    36.                     rayOpposing = new Ray(reversePoint, -reverseVector);
    37.                     hitInfosReverse = Physics.RaycastAll(rayOpposing, reverseRayDistance);
    38.                     for (int hitIndexRev = 0; hitIndexRev < hitInfosReverse.Length; hitIndexRev++)
    39.                     {
    40.                         if (hitInfos[hitIndex].transform == hitInfosReverse[hitIndexRev].transform)
    41.                         {
    42.                             minDistance = Vector3.Distance(hitInfosReverse[hitIndexRev].point, hitInfos[hitIndex].point);
    43.                         }
    44.                     }
    45.  
    46.                     // here use the minDistance
    47.                 }
    48.  
    49.                 targetX += calculationResolution;
    50.             }
    51.             targetZ += calculationResolution;
    52.         }
    53.     }
    54.  
     
  2. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,423
    Very good description of the problem :)

    If your objects are primitive shapes only then I'm sure that an analytical way for computing those segments exists. I've had to do something similar for computing the area of the surface of a liquid inside a cylindrical tank. For ellipses, there are many formulas involving the chords. However, I think this question would better fit in some other forum specialized on math and geometry.

    If your objects are arbitrary convex colliders, then I don't see a better option that the double raycast. I feel that any analytical approach here would be essentially reproducing the Raycast procedure. A possible optimization is using Collider.Raycast instead of Physics.Raycast. Collider.Raycast casts a ray on a specific collider only, bypassing the broad phase collision detection for the ray.
     
  3. Kobus

    Kobus

    Joined:
    Mar 27, 2015
    Posts:
    48
    Thank you Edy.
    Unfortunately the current and future objects are and will be arbitrary convex colliders. The Collider.Raycast sounds like a good option. I shall play with that and see how it works.
     
    Edy likes this.