views:

423

answers:

1

Hi,

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:

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?

+1  A: 

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.

comingstorm
I just want to thank you for your help. It was a really hard problem for me, but I figured it out. :) The answer lay in calculating new x and y axes based on the directional vector of the camera as the new z axis. After that, it became a matter of a simple ray-plane intersection and dotting the intersection point with the new x and y axes.
knight666