views:

53

answers:

1

How do I do a perspective view transformation in Java? As I understand it there is some magical 4 dimensional matrix I can use which will determine the FOV, Aspect Ratio, and Near and Far viewing distances, but I don't know how to create that matrix.

I'm able to implement a "PerspectiveTransform" in Java, but I see no effect when using the following

double mat[][] = {
    {1, 0, 0, 0}, 
    {0, 1, 0, 0},
    {0, 0, 1, 0},
    {0, 0, 1, 0}};
PerspectiveTransform ps = new PerspectiveTransform(mat);
ps.transform(p1, p1);
ps.transform(p2, p2);
ps.transform(p3, p3);
ps.transform(p4, p4);

I understand the the bottom-most "1" may need to be 1/d where "d" is the distance, but no matter what number I try there I get no effect. Changing the other numbers does have an effect, but I don't know what effect they will have until I try it (and I can't just guess infinitely). I am aware of and was able to get the "quadToQuad" function to work, but again I would have to guess at which "quads" to use.

So I need a resource to explain to me how to come up with the matrix I need based on a FOV, aspect ratio, distance, etc. I've read the pertinent portion of "Interactive Computer Graphics" 5th Ed. by Edward Angel and don't understand it.

What I'm trying to do is convert a bird's-eye-view image into a human-eye-view image. An example of this can be seen when using Google Earth..

thanks

A: 

There is the possibility that when you do ps.transform(p2, p2) you are canceling the effect of the same instruction with the p1 as argument, but regardless that, the typical meaning of the positions of that matrix are as follows:

alt text

This link might be able to give you a little hand with this.
Also in here, you can check how to calculate the field of view, on section "Setting the Projection Tranform"

In your case, I believe your matrix should have the last line set as 0 0 0 1 instead of how it is like. Also, the field of view can be calculated through the expression described in that same link:

void VerticalFieldOfView(float degrees, float aspectRatio, 
                         float near, float far)
{
   float top = near * std::tan(degrees * Pi / 360.0f);
   float bottom = -top;
   float left = bottom * aspectRatio;
   float right = top * aspectRatio;

   glFrustum(left, right, bottom, top, near, far);
}

Where the "glFrustum(...)" is

void ApplyFrustum(float left, float right, float bottom, 
                  float top, float near, float far)
{
    float a = 2 * near / (right - left);
    float b = 2 * near / (top - bottom);
    float c = (right + left) / (right - left);
    float d = (top + bottom) / (top - bottom);
    float e = - (far + near) / (far - near);
    float f = -2 * far * near / (far - near);

    mat4 m;
    m.x.x = a; m.x.y = 0; m.x.z = 0; m.x.w = 0;
    m.y.x = 0; m.y.y = b; m.y.z = 0; m.y.w = 0;
    m.z.x = c; m.z.y = d; m.z.z = e; m.z.w = -1;
    m.w.x = 0; m.w.y = 0; m.w.z = f; m.w.w = 1;

    glUniformMatrix4fv(projectionUniform, 1, 0, m.Pointer());
}

The example is in C++ but all you have to do is translate it into two Java functions, and also use the correspondant methods for making your matrix uniform at the end.

Luis Miguel
Okay, so here's what I don't understand about the links provided... It seems like the labeled matrix, with rightX, rightY, eyeX, eyeY, eyeZ, etc. means that I'm supposed to pretend that my 2d image is 3d and invent a point for the eye/camera and a point that the eye is looking at. So which points do I use? Neither of the links seem to mention a FOV or distance at all. The second one mentions "near and far," but doesn't say anything about how to choose these numbers, or how to choose the eyeX, eyeY, eyeZ, etc. Is there something I'm missing?
Aaron
Ok, first of all, whenever you use 4x4 dimensions you are referring to 3D space, which means that for what concerns bidimentional things, you will basically fix one of the axis, to determine the plane in which you're working. You always work with one extra unit of size in the matrix than the dimension of the space you are working on in order to make the matrix square, which simplifies operations with it.As far as I know, you cannot use this method to actually change your perspective of an image, unless that image is actually your screen and is expressed in a 3D virtual environment.
Luis Miguel
"cannot use this method to actually change your perspective of an image"... So.. Are you saying I can't change the perspective of a 2d image using a 4x4 matrix?
Aaron
You can change the 3D perspective over your 2D image. The image itself will be the same, but you will be changing the perspective you are using to look at it. I wasn't sure if you had that clear.
Luis Miguel