Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java OpenGL - Calculating orthographic frustum for isometric view

Tags:

java

opengl

jogl

I'm trying to figure out how to correctly calculate the frustum bounds of my openGL scene under Orthographic Projection. The code I'm using to do so is as follows:

public void setFrustum(GL gl, GLU glu){

    double[] forwardAxis = properties.getForwardAxis();
    double[] leftAxis = VecMath.normalVector(properties.getUpDir(), forwardAxis);
    double[] upAxis = VecMath.normalVector(forwardAxis, leftAxis);

    double[] v = bounds.getWidthVector();

    double width = VecMath.magnitude(VecMath.project(v, leftAxis));
    double height = VecMath.magnitude(VecMath.project(v, upAxis));

    double modelRatio = width / height;
    double canvasRatio = properties.getAspectRatio();
    // -- height bigger than width --
    if (modelRatio < canvasRatio){
        // -- update width --
        width = height * canvasRatio;
    } else{
        // -- update height --
        height = width / canvasRatio;
    }

    double l = width / 2. * 1.15;
    double b = height / 2. * 1.15;
    double n = properties.getNear();
    double f = properties.getFar();
    gl.glOrtho(-l, l, -b, b, n, f);
}

So as you can see I get my axes and my width vector:

widthVector = (xWidth, yWidth, zWidth)

and then get the width and height of the gl scene by projecting this width vector along the leftAxis and upAxis. I then match the aspectRatio to that of the canvas I'm displaying this scene in and use the width and height to calculate the bounds of the orthographic frustum (adding padding using the 1.15 scaling factor).

This works quite well for all views except the Isometric view. Here are some screen shots of this at work:

BottomView LeftView FrontView

IsometricView

As you can see, the bottom, left and front views are all fine. However, the isometric view is chopped off (and no I didn't clip it wrong when taking the screenshot!). I would have to increase the padding scale factor I use to 1.5 instead of 1.15, but I must be doing something wrong here.

Any help would be greatly appreciated. Thanks!

like image 912
CB_Maverick Avatar asked Oct 20 '22 00:10

CB_Maverick


2 Answers

This is my fitAllIn simplified

public void fitAllIn(float[] boundingMinMaxWorldSpace) {

        Vec4 centerWorldSpace = new Vec4((boundingMinMaxWorldSpace[0] + boundingMinMaxWorldSpace[1]) / 2,
                (boundingMinMaxWorldSpace[2] + boundingMinMaxWorldSpace[3]) / 2,
                (boundingMinMaxWorldSpace[4] + boundingMinMaxWorldSpace[5]) / 2, 1f);

        Vec3 min = new Vec3(boundingMinMaxWorldSpace[0], boundingMinMaxWorldSpace[2], boundingMinMaxWorldSpace[4]);
        Vec3 max = new Vec3(boundingMinMaxWorldSpace[1], boundingMinMaxWorldSpace[3], boundingMinMaxWorldSpace[5]);

        float diameter = (float) Math.sqrt(
                (max.x - min.x) * (max.x - min.x)
                + (max.y - min.y) * (max.y - min.y)
                + (max.z - min.z) * (max.z - min.z));

        if (getCurrView().orthographicProj) {

            if (glViewer.getAspect() > 1) {
                // projection * scale = y
                getCurrView().scale = diameter / 2 / projectionSide;

            } else {
                // projection * aspect * scale = x
                getCurrView().scale = diameter / 2 / (projectionSide * glViewer.getAspect());
            }
            getCurrView().scale = viewScale.clampScale(projectionSide, getCurrView().scale);
        }
    getCurrView().targetPos = new Vec3(centerWorldSpace);

    glViewer.refresh();

Basically I pass the bounding box in world space, I calculate the center that my camera will target, I calculate the minimum point (minX, minY, minZ) and the maximum one. I get the diameter and then a simple equation to retrieve the scaling.

scale and projectionSide will be used later for the elaboration of my orthographic matrix

        float x = projectionSide * glViewer.getAspect() * getCurrView().scale;
        float y = projectionSide * getCurrView().scale;
        float z = projectionSide;

        return Jglm.orthographic(-x, x, -y, y, -z, z);
like image 69
elect Avatar answered Oct 24 '22 13:10

elect


Thanks to the suggestion of elect, here is my updated setFrustum routine:

public void setFrustum(GL gl, GLU glu) {

    double[] widthVec = bounds.getWidthVector();

    double diameter = VecMath.magnitude(widthVec);

    double canvasRatio = properties.getAspectRatio();

    double scale = canvasRatio > 1 ? diameter / 2 : diameter / 2 / canvasRatio;

    double x = canvasRatio * scale;
    double y = scale;

    double n = properties.getNear();
    double f = properties.getFar();
    gl.glOrtho(-x, x, -y, y, n, f);
}

Works perfectly. Thanks Elect!

like image 33
CB_Maverick Avatar answered Oct 24 '22 11:10

CB_Maverick