Search Unity

Need algorithm for depenetrating sphere from wall in a direction

Discussion in 'Physics' started by HiddenMonk, Nov 23, 2015.

  1. HiddenMonk


    Dec 19, 2014
    I am looking for a way to depenetrate a sphere that is inside a wall (Plane) in any direction.

    In the image above, the black sphere is where my sphere currently is, and the brown line represents the wall. The red dot is the closest point of the wall to the center of the sphere and the orange arrow is that walls normal. The goal is to move my sphere in what ever direction I choose enough so that it is no longer touching the wall. So the goal position is represented by the blue sphere.

    Currently, I am doing a SpherePlaneSweep test towards to spheres position as described here
    however, I am wondering if there is a more simpler way of handling this.

    I appreciate any help!

    Edit -
    We can use SohCahToa to find our answer. In our case we are using Soh (opposite over hypotenuse) since we know the angle between the normal and the desired depenetration direction as well as the length of the opposite side, which is the radius - distance from sphere center to the normal plane.

    Here is an image example.
    The dark green line is the radius - distance, the brown line is the plane, the light green is the normal, and the light blue is our depenetration direction. The red line is just the dark green line moved down the light blue line until it is no longer behind our wall. You can now see a triangle formed between the light blue, brown, and red line. We get the angle between our blue line and light green line and minus that by 90 to get the angle of the triangle. Now we have an angle and a length of one side of the triangle. This is enough to use SohCahToa to get another lines length, which in our case is the length of that blue line within the red and green line (the hypotenuse). That distance is how much we need to move our sphere in our depenetration direction.

    Click for code.
    Code (CSharp):
    2.     //We use Soh from SohCahToa
    3.     Vector3 DepenetrateSphereFromPlaneInDirection(Vector3 spherePosition, float radius, Vector3 depenetrationDirection, Vector3 planePoint, Vector3 planeNormal)
    4.     {
    5.         planeNormal.Normalize(); //just in case
    7.         float distance = LinePlaneDistance(spherePosition, -planeNormal, planePoint, planeNormal);
    8.         if(Mathf.Abs(distance) < radius)
    9.         {
    10.             distance = radius - distance;
    11.             float angle = Mathf.Abs(90f - Vector3.Angle(depenetrationDirection, planeNormal));
    12.             if(angle > 0)
    13.             {
    14.                 float depenetrationDistance = distance / Mathf.Sin(angle * Mathf.Deg2Rad);
    15.                 return spherePosition + (depenetrationDirection * depenetrationDistance);
    16.             }
    17.         }
    19.         return;
    20.     }
    22.     float LinePlaneDistance(Vector3 linePoint, Vector3 lineVec, Vector3 planePoint, Vector3 planeNormal)
    23.     {
    24.         //calculate the distance between the linePoint and the line-plane intersection point
    25.         float dotNumerator = Vector3.Dot((planePoint - linePoint), planeNormal);
    26.         float dotDenominator = Vector3.Dot(lineVec, planeNormal);
    28.         //line and plane are not parallel
    29.         if(dotDenominator != 0f)
    30.         {
    31.             return dotNumerator / dotDenominator;
    32.         }
    34.         return 0;
    35.     }
    Last edited: Aug 19, 2016