Fredrik Johansson
Fredrik Johansson

Reputation: 3535

GetPoint() in Ray but with Padding and Angle

This might be an odd question, but as fairly new to Unity I don't know how to go about my problem, but I find the Ray() class as one of the most useful classes for all kinds of work. Anyhow, to compute a given point of a Ray it's easy to call .GetPoint(distance). - But is there a way to do a call like .GetPoint(distance, padding, angle)?

For instance, given the (3D) Ray from a to b

a--c----b
   |
   d

A call to .GetPoint(3) would return c, and a call to the wanted/new method .GetPoint(3, 2, 0) should return d. Further, calling .GetPoint(3, 2, 90) should return d when it's behind (or above) c.

I guess I should have paid more attention in math class...

Upvotes: 0

Views: 163

Answers (1)

Ruzihm
Ruzihm

Reputation: 20249

If you don't mind Unity finding an arbitrary starting point, you can use Vector3.OrthoNormalize to get a starting point for you.

Then, you can use Quaternion.AngleAxis to rotate the point around the ray's direction (you have to offset the ray to/from the origin for the rotation operation).

Vector3 GetPaddedPoint(Ray ray, float distance, float padding, float angleInDegrees) 
{
    Vector3 rayDirection = ray.direction;
    Vector3 startingOrtho;
    Vector3.OrthoNormalize(ref rayDirection, ref startingOrtho);

    // Find some point padding from ray at distance from origin
    Vector3 axisPoint = ray.GetPoint(distance);
    Vector3 startingPoint = padding * startingOrtho+ axisPoint;

    // Find where startingPoint would be if the origin of the ray was at the origin
    Vector offsetPoint = startingPoint - ray.origin;

    // Rotate the offsetPoint around ray direction using Quaternion
    Quaternion rotation = Quaternion.AngleAxis(angleInDegrees, rayDirection);
    Vector3 rotatedOffsetPoint = rotation * offsetPoint;

    // Add back in the ray's origin
    return rotatedOffsetPoint + ray.origin;

}

If you find that you prefer a particular kind of direction for a starting point, you can pass in a startingOrtho. Keep the OrthoNormalize call to ensure that it startingOrtho becomes orthogonal to the ray and normalized if it isn't already.

Vector3 GetPaddedPoint(Ray ray, float distance, float padding, float angleInDegrees, Vector3 startingOrtho) 
{
    Vector3 rayDirection = ray.direction;
    Vector3.OrthoNormalize(ref rayDirection, ref startingOrtho);

    // Find some point padding from ray at distance from origin
    Vector3 axisPoint = ray.GetPoint(distance);
    Vector3 startingPoint = padding * startingOrtho+ axisPoint;

    // Find where startingPoint would be if the origin of the ray was at the origin
    Vector offsetPoint = startingPoint - ray.origin;

    // Rotate the offsetPoint around ray direction using Quaternion
    Quaternion rotation = Quaternion.AngleAxis(angleInDegrees, rayDirection);
    Vector3 rotatedOffsetPoint = rotation * offsetPoint;

    // Add back in the ray's origin
    return rotatedOffsetPoint + ray.origin;

}

Upvotes: 1

Related Questions