Marco83
Marco83

Reputation: 1191

Unable to maintain uniform scale when resizing window, OpenGL + Java = JOGL

I'm using JOGL (Java OpenGL wrapper) for the first time and I have an issue I can't figure out, I'm not sure if this is related to JOGL or OpenGL in general.

I render on a GLCanvas inside a JPanel inside a JForm (the whole point of the program is to mix OpenGL and SWING). As of now I'm drawing simple 2D (ortho) triangles (they'll be tiles), I would like them to scale according to the size of the viewport (panel?). I achieved scaling but for some reason the image is stretched, as if scale ratio was not the same on the X component and the Y component, when I resize the window. I.e. they should maintain the same square ratio, but they get stretched instead.

As you can see in the code, I use the same zoom factor for X and Y.

I don't understand if the error is in my OpenGL code or in my SWING-JOGL code. Can anyone point me in the right direction?

An image is better than a thousands words: The streching effect after resizing the window

Here's some code:

The OpenGL code

class Graphics {

/**
 * The default ratio between the screen size and the tile size, before zoom is applied
 */
final static float DEFAULT_TILE_TO_SCREEN = 0.5f;

/**
 * The parent engine
 */
protected Engine myEngine; 

Graphics(Engine e)
{
    myEngine = e;
}

/**
 * Sets up viewport
 * @param gl2
 * @param width
 * @param height 
 */
void setup( GL2 gl2, int width, int height ) {
    gl2.glMatrixMode( GL2.GL_PROJECTION );
    gl2.glLoadIdentity();

    // coordinate system origin at lower left with width and height same as the window
    GLU glu = new GLU();
    glu.gluOrtho2D( 0.0f, width, 0.0f, height );

    gl2.glMatrixMode( GL2.GL_MODELVIEW );
    gl2.glLoadIdentity();

    gl2.glViewport( 0, 0, width, height );
}

/**
 * Renders viewport
 * @param gl2
 * @param width
 * @param height 
 */
void render( GL2 gl2, int width, int height ) {
    final float zoomFactor = DEFAULT_TILE_TO_SCREEN * myEngine.myZoomLevel;
    final float zoom = Math.max(height *  zoomFactor, width * zoomFactor);
    gl2.glClear( GL.GL_COLOR_BUFFER_BIT );

    // draw a triangle filling the window
    gl2.glLoadIdentity();
    gl2.glScalef(zoom, zoom, 1);
    gl2.glBegin( GL.GL_TRIANGLES );
    for(int x = 0; x < myEngine.myWorldTiles.maxTileX; ++x)
    {
        for(int y = 0; y < myEngine.myWorldTiles.maxTileY; ++y)
        {
            gl2.glColor3f( 1, 0, 0 );
            gl2.glVertex2f( x + 0.f, y + 0.f );
            gl2.glVertex2f( x + 1.f, y + 0.f );
            gl2.glVertex2f( x + 1.f, y + 1.f );

            gl2.glColor3f( 0, 0, 1 );
            gl2.glVertex2f( x + 0.f, y + 0.f );
            gl2.glVertex2f( x + 1.f, y + 1.f );
            gl2.glVertex2f( x + 0.f, y + 1.f );
        }
    }
     gl2.glEnd();
}

}

The SWING integration code

public class Engine {

/**
 * The internal rendering canvas
 */
private GLCanvas    myCanvas;
/**
 * The graphics used for rendering
 */
private Graphics    myGraphics;   

/**
 * The zoom level of the graphics
 */
float       myZoomLevel = 1;
/**
 * The world map
 */
TileList    myWorldTiles;

/**
 * The currently centered tile
 */
Point       myCenteredTile;

public Engine(TileList worldTile)
{
    myWorldTiles = worldTile;
    GLProfile glprofile = GLProfile.getDefault();
    GLCapabilities glcapabilities = new GLCapabilities( glprofile );
    myCanvas = new GLCanvas( glcapabilities );

    myGraphics = new Graphics(this);
    myCanvas.addGLEventListener( new GLEventListener() {

        @Override
        public void reshape( GLAutoDrawable glautodrawable, int x, int y, int width, int height ) {
        }

        @Override
        public void init( GLAutoDrawable glautodrawable ) {
            myGraphics.setup( glautodrawable.getGL().getGL2(), glautodrawable.getWidth(), glautodrawable.getHeight() );
        }

        @Override
        public void dispose( GLAutoDrawable glautodrawable ) {
        }

        @Override
        public void display( GLAutoDrawable glautodrawable ) {
            myGraphics.render( glautodrawable.getGL().getGL2(), glautodrawable.getWidth(), glautodrawable.getHeight() );
        }
    });

}

/**
 * Sets the zoom level for the screen
 * @param zoom 
 */
public void setZoomLevel(float zoom)
{
    myZoomLevel = zoom;
}

/**
 * Gets the 3D canvas, should be placed in user-defined form/window/panel 
 */
public java.awt.Component getCanvas()
{
    return myCanvas;
}

/**
 * Centers the screen on the given tile
 * @param p 
 */
public void centerOnTile(Point p)
{
    myCenteredTile = p;
}
}

Also

in the JFrame init code

contentPanel.add(myWorld.myEngine.getCanvas(), BorderLayout.CENTER);

Upvotes: 0

Views: 2331

Answers (1)

rgngl
rgngl

Reputation: 5423

You have to setup the projection matrix each time the window resizes. I haven't used JOGL before but I think you should do it in that reshape method in the code.

Upvotes: 2

Related Questions