1
votes

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

1
Also note that this isn't java-specific.Rob Lourens

1 Answers

1
votes

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
(source: google.com)

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.