Skip to content

Instantly share code, notes, and snippets.

@v21
Created April 13, 2013 10:20
Show Gist options
  • Save v21/5377854 to your computer and use it in GitHub Desktop.
Save v21/5377854 to your computer and use it in GitHub Desktop.
> Okay. Maths is beyond me, so: I want to get a tangental line to a 3D line at a random angle & random point along it, of a random length.How? Like this:
Vector3 randomVector = Random.onUnitSphere;
Plane plane = new Plane(randomVector, start, end);
float breakPoint = Random.value;
Vector3 candidatePoint = plane.normal * Random.value * maxBreakDistanceFromPath + (end - start) * breakPoint + start;
return candidatePoint;
@paulsinnett
Copy link

I'm not sure this does what you want. (From the code it seems that you want a perpendicular line rather than a tangent. A tangent would just be the same line again. So I'm assuming that it's actually a perpendicular line that you're after.)

It seems that this code ought to produce perpendicular lines in most cases. I think it could fail if the random point, start, and end that you use to create the plane end up being co-linear. In the general case I think the results will be biased towards perpendicular lines that are also tangential to a sphere about the origin. So if you were to run it iteratively it would eventually plot out the rough shell of a sphere.

To make it a bit more random, what I'd suggest is to find an arbitrary perpendicular, and rotate it by a random angle using the line itself as the axis of rotation.

As input to the function I'd suggest you give it a Ray and a length. That way, if you end up passing in a line with a small length, the maths won't break down.

To find an arbitrary perpendicular, you need to find the cross product of your ray.direction and an arbitrary other vector that is not co-linear or nearly co-linear. The easiest way to do this is to find the smallest component of the ray.direction and use the global axis in that direction:

if (Mathf.Abs(ray.direction.x) < Mathf.Abs(ray.direction.y) && Mathf.Abs(ray.direction.x) < Mathf.Abs(ray.direction.z))
    divergent = Vector3.right;
else if (Mathf.Abs(ray.direction.y) < Mathf.Abs(ray.direction.x) && Mathf.Abs(ray.direction.y) < Mathf.Abs(ray.direction.z))
    divergent = Vector3.up;
else
    divergent = Vector3.forward;

perpendicular = Vector3.Cross(ray.direction, divergent).normalized;

Then, to rotate this vector around the original ray:

newRay.direction = Quaternion.AngleAxis(randomAngle, ray.direction) * perpendicular;

P.S. the above is a completely untested brain dump

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment