0
\$\begingroup\$

I have a weird problem and I have no idea what's going on with it.

Recently started doing some OpenGL programming, going pretty well, hit some rough spots but worked my way through them and otherwise pretty happy! But I've hit a roadblock with something that has me confused as hell.

I'm doing an OpenGL 4 based rendering system, it's early days and I've got some basic stuff like 3D model importer happening, but I've been having some problem with the maths involved in creating my own "LookAt" function like present in OpenGL 2. I've created my own Matrix & Vector class, I think most of the functions are right but the LookAt does something weird when looking at different angles.

For a simple test to show what happens, I created a slowly moving focus point for the lookat that starts off a few units ahead of the camera, then slowly moves closer and closer till it's 1 unit below the camera. As the focus point comes closer to the point of looking straight down, for some reason it's like the field of view is narrowing?

enter image description here

It eventually zooms in so close that all you can see is one solid colour covering the entire screen, whatever pixel just happens to be on the ground directly below the camera as it zooms in with a field of view of basically 0 degrees.

It may be nothing to do with field of view at all but I don't know and hence why I'm here. Here is some related code to the problem, forgive me if these implementations are not perfect, again I'm just starting out and I don't know the best methods yet, still learning:

My function for calculating a lookAt:

public static Transformation lookAt(Vector position, Vector target, Vector updirection) {
        Transformation lookAt = new Transformation();

        Vector vz = position.clone();
        vz.subtract(target);
        vz.normalise();

        Vector vx = Vector.xProduct(updirection, vz);
        vx.normalise();

        Vector vy = Vector.xProduct(vz, vx);

        lookAt.m[0] = vx.x; lookAt.m[1] = vy.x; lookAt.m[2] = vz.x; lookAt.m[3] = position.x;
        lookAt.m[4] = vx.y; lookAt.m[5] = vy.y; lookAt.m[6] = vz.y; lookAt.m[7] = position.y;
        lookAt.m[8] = vx.z; lookAt.m[9] = vy.z; lookAt.m[10] = vz.z; lookAt.m[11] = position.z;
        lookAt.m[12] = 0; lookAt.m[13] = 0; lookAt.m[14] = 0; lookAt.m[15] = 1;

        return lookAt.inverse();
    }

My function for calculating perspective:

public static Transformation perspective(double FoV, double aspectRatio, double nearClip, double farClip) {
    Transformation proj = new Transformation();
    double FoVR = Math.toRadians(FoV);
    proj.m[0] = FoVR/aspectRatio;
    proj.m[5] = FoVR;
    proj.m[10] = (farClip + nearClip)/(nearClip - farClip);
    proj.m[11] = 2*(farClip*nearClip)/(nearClip-farClip);
    proj.m[14] = -1;
    proj.m[15] = 0;
    return proj;
}

I use the function later on when generating a matrix to apply to the 3D letter G in the scene, like so:

Transformation MVP = new Transformation();

Transformation proj = Transformation.perspective(FoV, (double)canvas.getWidth()/(double)canvas.getHeight(), near, far);
MVP.multiply(proj);

Transformation view = Transformation.lookAt(cameraPosition, cameraFocus, cameraUp);
MVP.multiply(view);

Transformation model = Transformation.scaleRotateTranslate(objectScale, objectRotation, objectTranslation);
MVP.multiply(model);

And the MVP is simply sent to the shader and used as you'd expect to multiple against all the verticies/normals.

What do you think I'm doing wrong? What should I check first? Is there a better way of doing what I'm trying to do? Any help/answers at all is greatly appreciated, I just don't know what to go after first. The perspective/lookAt seems like it's almost working but something must be broken?

\$\endgroup\$
0
\$\begingroup\$

I got help in another part of this website on a similar question which answered this one. As such I'm going to answer my own question here and supply the answer I was given just to close this.

So what I really needed was a working LookAt function, I'm still not sure what exactly was causing the problem I had before with the weird distortion other than simply using the wrong method. But my new LookAt function DOES work and make more sense so I'll supply the code.

I received my answer in this question, the info I was given was very helpful and worth checking out:

3D Camera Rotation

New "lookAt" function:

public static Mat4 lookAt(Vec4 position, Vec4 target, Vec4 updirection) {
    Vec4 zaxis = position.minus(target).normalise();
    Vec4 xaxis = Vec4.crossProduct(updirection, zaxis).normalise();
    Vec4 yaxis = Vec4.crossProduct(zaxis, xaxis);

    Mat4 orientation = new Mat4(new float[] {
        xaxis.x, xaxis.y, xaxis.z, 0,
        yaxis.x, yaxis.y, yaxis.z, 0,
        zaxis.x, zaxis.y, zaxis.z, 0,
        0,      0,      0,      1
    });

    Mat4 translation = Mat4.translation(-position.x, -position.y, -position.z);

    return orientation.multiply(translation);
}

Disclaimer: But before you use that code, do check the other link, as this seems to work but for all I know it may have a hidden problem in it, so check the other info first!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.