I have drawn a 2D representation of the problem, but I will eventually have to solve this in 3 dimensions.
A line is drawn from an origin point to infinity, in a direction given by pitch and yaw. There is an axis-aligned box "in front of" the point.
I want to get the coordinates of the point on box that is closest to the line, or, if it intersects, closest to the origin point.
I.e., if the line were 'turned' towards the box, which point of the box would intersect with the line first?
Make parametric represenation of the ray with base point P0, direction vector D and parameter t
P = P0 + t * D
Get t for intersections of the ray with rectangle edges like this (similar in 3d):
Rect.Right = X0 + t * D.X
Find what intersection occurs first (smaller t), check coordinates of intersection. If inside edge - point found. If not, analyze intersection parameters with edgr continuations to determine what corner (perhaps edge in 3d) is the closest
Note that in 2d case you need to check only two possible edges - depending on ray direction. For example - left and bottom for your right picture. When you see that intersections are out of edges - check what of two corners is closer. The same for 3d - but intersection is possible for three faces and closest for more edges or corners.
Let the position of the point be (x0,y0,z0) and the box have corners (x1,y1,z1) and (x2,y2,z2) with x1 < x2, y1 < y2, z1 < z2. In terms of yaw ψ and pitch θ a unit vector along the line will be give by
(u,v,w) = (cos ψ sin θ, sin ψ, cos ψ cos θ)
The line is (x0,y0,z0) + t (u,v,w)
Finding intersection with one of the plane containing a face of the box is trivial. Say to find the intersection with the plane x=x1, just requires solving
x0 + u t = x1 so t = (x1-x0)/u. Once found its easy to check if the intersection is contained in the face.
The tricky situation happens if the line does not intersect the faces. Here we have a pair of skew lines, and wish to find the closest pair of points one on each line.
Consider the closest point to the edge from (x1,y1,z1) to (x2,y1,z1).
We want to find the parameter s,t such that that the points
(x0,y0,z0)+s(u,v,w)
(x1,y1,z1)+t(1,0,0)
are the closest. The segment joining these points must be perpendicular to both lines. A vector along that line is the cross product
N = (u,v,w) X (1,0,0) = (0,w,-v)
Now consider the plane through (x1,y1,z1) spanned by (1,0,0) and N, this has normal
N2 = (1,0,0) X N
= (1,0,0) X (0,w,-v)
= (0,v,w)
and the plane is defined by
P . N2 = (x1,y1,z1) . N2
Take a point on our ray
( (x0,y0,z0)+s(u,v,w) ) . N2 = (x1,y1,z1) . N2
(x0,y0,z0) . N2 + s (u,v,w) . N2 = (x1,y1,z1) . N2
s (u,v,w) . N2 = ((x1,y1,z1)-(x0,y0,z0)) . N2
s (v^2+w^2) = (y1-y0) v + (z1-z0) w
so
s = [ (y1-y0) v + (z1-z0) w ] / (v^2+w^2)
We can repeat the above for each edge on the box, find the closest points and select the smallest.
I have got a camera and the direction it is looking at. Therefore I can create a plane out of this direction vector if I take it as a normal vector. So now I want to move my camera which should be on this plane along the plane. Everything's in 3D but I couldn't come up with an idea how to do so. How can I implement the navigational method of panning - so moving in this specific plane?
To pan your camera to the left and to the right you need to know not only lookAt direction, but also up direction for the camera. Then you can calculate cross product of lookAt and upAxis and this gives you direction to the right, negated vector gives you direction to the left.
Definition: A vector N that is orthogonal to every vector in a plane is called a normal vector to the plane.
An equation of the plane containing the point (x0, y0, z0) with normal vector N = (A, B, C), is A(x − x0) + B(y − y0) + C(z − z0) = 0.
Note: The equation of any plane can be expressed as Ax + By + Cz = D.
This is called the standard form of the equation of a plane. From the eqn you can get any other point you want on the plane.
Example: A plane passing through the point P = (1, 6, 4) and the normal vector, R = (2, - 3, - 1). Then the eqn is,
2(x-1) - 3(y-6) - (z-4) = 0
=> 2x - 3y - z = -20
I'm trying to write a function that returns true if a ray intersects a sphere and the code I'm referencing goes something like this:
// given Sphere and Ray as arguments
invert the Sphere matrix
make new Ray object
origin of this object = old Ray origin * inverted Sphere matrix
direction = old Ray direction * inverted Sphere matrix
a = |new direction| ^ 2
b = dot product of new origin and new direction
c = |new origin| ^ 2 - 1
det = b*b - a*c
if det > 0 there is an intersection
I'm stuck at understanding why we need to invert the Sphere matrix first and then multiply it to the Ray's origin and direction. Also I'm confused how to derive the quadratic equation variables a, b, and c and the end. I know I have to combine the parametric equations for a ray (p + td) and for a circle (x dot x - 1 = 0) but I can't figure out how to do so.
You need to invert the sphere matrix to have the ray in the sphere's coordinate frame, which, if the sphere is not scaled, is the same as simply setting new_origin = origin - sphere_center (and using the original direction)
The equation is formed from the formula:
|new_dir*t + new_origin|^2 = r^2 (presumably r is 1)
If you expand it, you get:
|new_dir|^2*t^2 + 2*(new_origin·new_dir)*t + |new_origin|^2-r^2 = 0
I have a polygon defined by n points and a polygon normal.
Now I want to get the plane of the polygon defined by
a plane normal=(nx,ny,nz)
and a constant d (distance from the origin to the plane).
The plane normal is equal to the polygon normal, but how can I calculate d?
desired plane equation nx*x+ny*y+nz*z+d=0.0
Take any point p=(px, py, pz) on the plane and plug it into the equation to obtain d.
So if your equation is
nx·x + ny·y + nz·z + d = 0
then you get
d = − (nx·px + ny·py + nz·pz).
Another common formulation is using d as the right hand side of the equation, in which case you get the reverse sign. I.e. for the equation
nx·x + ny·y + nz·z = d
you get
d = nx·px + ny·py + nz·pz.
My problem:
How can I take two 3D points and lock them to a single axis? For instance, so that both their z-axes are 0.
What I'm trying to do:
I have a set of 3D coordinates in a scene, representing a a box with a pyramid on it. I also have a camera, represented by another 3D coordinate. I subtract the camera coordinate from the scene coordinate and normalize it, returning a vector that points to the camera. I then do ray-plane intersection with a plane that is behind the camera point.
O + tD
Where O (origin) is the camera position, D is the direction from the scene point to the camera and t is time it takes for the ray to intersect the plane from the camera point.
If that doesn't make sense, here's a crude drawing:
I've searched far and wide, and as far as I can tell, this is called using a "pinhole camera".
The problem is not my camera rotation, I've eliminated that. The trouble is in translating the intersection point to barycentric (uv) coordinates.
The translation on the x-axis looks like this:
uaxis.x = -a_PlaneNormal.y;
uaxis.y = a_PlaneNormal.x;
uaxis.z = a_PlaneNormal.z;
point vaxis = uaxis.CopyCrossProduct(a_PlaneNormal);
point2d.x = intersection.DotProduct(uaxis);
point2d.y = intersection.DotProduct(vaxis);
return point2d;
While the translation on the z-axis looks like this:
uaxis.x = -a_PlaneNormal.z;
uaxis.y = a_PlaneNormal.y;
uaxis.z = a_PlaneNormal.x;
point vaxis = uaxis.CopyCrossProduct(a_PlaneNormal);
point2d.x = intersection.DotProduct(uaxis);
point2d.y = intersection.DotProduct(vaxis);
return point2d;
My question is: how can I turn a ray plane intersection point to barycentric coordinates on both the x and the z axis?
The usual formula for points (p) on a line, starting at (p0) with vector direction (v) is:
p = p0 + t*v
The criterion for a point (p) on a plane containing (p1) and with normal (n) is:
(p - p1).n = 0
So, plug&chug:
(p0 + t*v - p1).n = (p0-p1).n + t*(v.n) = 0
-> t = (p1-p0).n / v.n
-> p = p0 + ((p1-p0).n / v.n)*v
To check:
(p - p1).n = (p0-p1).n + ((p1-p0).n / v.n)*(v.n)
= (p0-p1).n + (p1-p0).n
= 0
If you want to fix the Z coordinate at a particular value, you need to choose a normal along the Z axis (which will define a plane parallel to XY plane).
Then, you have:
n = (0,0,1)
-> p = p0 + ((p1.z-p0.z)/v.z) * v
-> x and y offsets from p0 = ((p1.z-p0.z)/v.z) * (v.x,v.y)
Finally, if you're trying to build a virtual "camera" for 3D computer graphics, the standard way to do this kind of thing is homogeneous coordinates. Ultimately, working with homogeneous coordinates is simpler (and usually faster) than the kind of ad hoc 3D vector algebra I have written above.