调整窗口大小时无法保持统一的比例,OpenGL + Java=JOGL
我第一次使用 JOGL(Java OpenGL 包装器),我有一个无法解决的问题,我不确定这是否与 JOGL 或 OpenGL 一般相关。
我在 JForm 内的 JPanel 内的 GLCanvas 上进行渲染(该程序的重点是混合 OpenGL 和 SWING)。截至目前,我正在绘制简单的 2D(正交)三角形(它们将是图块),我希望它们根据视口(面板?)的大小进行缩放。 我实现了缩放,但由于某种原因图像被拉伸,就好像当我调整窗口大小时 X 分量和 Y 分量的缩放比例不同。 即它们应该保持相同的平方比,但它们却被拉伸了。
正如您在代码中看到的,我对 X 和 Y 使用相同的缩放系数。
我不明白错误是在我的 OpenGL 代码中还是在我的 SWING-JOGL 代码中。 有人能指出我正确的方向吗?
一张图片胜过千言万语:
以下是一些代码:
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);
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:
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);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
每次调整窗口大小时都必须设置投影矩阵。我以前没有使用过 JOGL,但我认为您应该在代码中的
reshape
方法中执行此操作。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.