During my studies in 3D Mathematics, I have mostly found that projection is achieved with a view frustum described as a matrix which involves variables near/far plane. This isn’t how projection in papervision is done by default, so, this set me on to a new path for unprojecting coordinates. This new path uses the perspective matrix.
Without perspective matrix
I first wanted to use the unproject function to unproject an xy plane to a z position in camera space. What I ended up doing was “untransforming” my coordinates back to the mX/mY parameters, given focus as z. This alone caused me to abandon this approach, since if I were doing this, I may as well override unproject and rewrite it to achieve what the Coordinate Utility Class currently does since “untransforming” is an extra and unoptimal step in achieving my goal. Bless that utility class, I am quite sure it will never be used, but nonetheless may have served as knowledgeable a prospect to others as it has to me. If you know of a better way to do this that does not involve “untransforming” unprojected coordinates, please let me know.
With perspective matrix
Following is a function that will unproject an xy plane with variable z in camera space coordinates. This only works if useProjectionMatrix is set to true. With the projection matrix used to project coordinates in your world, we can use unproject techniques used in other 3D engines and/or languages:
public function unprojectMatrix(screen:Number3D):Number3D { if(useProjectionMatrix){ var s4:Quaternion = new Quaternion(screen.x, -screen.y, screen.z+focus); var up4:Quaternion = Quaternion.createFromMatrix(this._projection); up4 = Quaternion.multiply(s4, up4); var up3:Number3D = new Number3D(up4.x/up4.w, up4.y/up4.w, up4.z/up4.w); Matrix3D.multiplyVector3x3(transform, up3); return up3; } else { return unproject(screen.x, screen.y); } } public function getTrueScaleDistance():Number { return focus*zoom-focus; }
You can add these functions to an extended camera with projectionMatrix turned on, and it will unproject your coordinates to the xy plane at a given z depth described with the screen:Number3D parameter. You will need to make private var _projection protected. The point of this is to expose the projection matrix to the function and can also be exposed if the function is added to the Camera3D class directly.
A sample use of the extended camera:
var zDepth:Number = camera.getTrueScaleDistance(); var screen:Number3D = new Number3D(viewPort.containerSprite.mouseX, viewPort.containerSprite.mouseY, zDepth); var ray:Number3D = camera.unprojectMatrix(screen); ray= Number3D.add(new Number3D(camera.x, camera.y, camera.z), ray); plane.x = ray.x, plane.y = ray.y, plane.z = ray.z;
Where camera is a subclass of Camera3D with the adjustments outlined above.
What is happening?
This is something I realized I would need before I found out how to do. When I was reading about Quaternions, it explained why and how William Rowan Hamilton realized that he needed them to begin with. I found that a Quaternion thought of as a division ring made more sense in the context of 3D math. We divide the x,y,z components of our 4D object (Quaternion) by the 4th dimension, w, after rotating our space in 4D. I think of w as a piece of information that carries the proportion of the lower dimensions so that by dividing them by w restores this proportion to renderable 3D coordinates. I have generalized this process to n-dimensions, maybe incorrectly. I will find out soon enough. If you have been with me since the start of my 3D math journey, you can think of w as perspective, and 1/w as equal to how we negated perspective.
That’s about where I’m at right now. Here is some sample code that does this. The source is intended to be compiled with the Flex compiler, but can be compiled by making Main the document object of a .fla document.
Interesting concepts. Have you thought about posing a function for projecting coordinates from a 3D plane onto the 2D screen we see as the flash window?
Hi James,
No, I haven’t considered it, but I believe there are some discussions on the papervision mailing list about this problem.
Thanks for the useful info. It’s so interesting