Невозможно поддерживать равномерный масштаб при изменении размера окна, OpenGL + Java = JOGL - PullRequest
0 голосов
/ 02 октября 2011

Я впервые использую JOGL (оболочку Java OpenGL), и у меня есть проблема, которую я не могу понять, я не уверен, связано ли это с JOGL или OpenGL в целом.

Я рендеринг на GLCanvas внутри JPanel внутри JForm (весь смысл программы в том, чтобы смешать OpenGL и SWING).На данный момент я рисую простые 2D (орто) треугольники (они будут плитками), я бы хотел, чтобы они масштабировались в соответствии с размером области просмотра (панели?).Я достиг масштабирования, но по какой-то причине изображение растянуто, как если бы я изменил размер окна, если масштабирование не было одинаковым для компонента X и компонента Y.Т.е. они должны поддерживать одинаковое квадратное соотношение, но вместо этого они растягиваются.

Как вы можете видеть в коде, я использую одинаковый коэффициент масштабирования для X и Y.

Я непонять, есть ли ошибка в моем коде OpenGL или в моем коде SWING-JOGL.Кто-нибудь может указать мне правильное направление?

Изображение лучше, чем тысячи слов: The streching effect after resizing the window

Вот код:

Код OpenGL

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();
}

}

Код интеграции SWING

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;
}
}

Также

в коде инициализации JFrame

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

1 Ответ

2 голосов
/ 02 октября 2011

Вы должны настраивать матрицу проекции каждый раз, когда размер окна изменяется.Я не использовал JOGL раньше, но я думаю, что вы должны сделать это в этом reshape методе в коде.

...