0

以下のコードでわかるように、キャンバスを含むJFrameを作成しました。私がやろうとしているのは、画面のサイズが更新されたときにopenGLコンテキストのサイズを変更することです。これは、resize()と呼ばれるイベントハンドラーで実行しているglViewport()の呼び出しと同じくらい簡単なはずです。ただし、その結果、次のようになります。

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at org.lwjgl.opengl.GL11.glViewport(GL11.java:3199)
at gltest.GameMain.resize(GameMain.java:149)
at gltest.GameMain$1.componentResized(GameMain.java:59)
(...)

私は完全に無知です。キャンバスのサイズから返された境界は問題ないようですが、ビューポートで使用するとエラーが発生します。代わりに「glViewport(1、1、100、100)」のようなビューポート呼び出しを行った場合も同じことが起こります。これらの値はすべてウィンドウの境界内にありますが、ウィンドウのサイズを変更すると、まったく同じnullPointerExceptionsがスローされます。

私はその理由を理解するためのアイデアとエネルギーが不足しています(私は3時間グーグルを続けていますが、結果はありません)。私は何が間違っているのですか?

import java.awt.Canvas;
import java.awt.Dimension;
import java.awt.GraphicsConfiguration;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;

import javax.swing.JFrame;

import org.lwjgl.LWJGLException;
import org.lwjgl.Sys;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;

import static org.lwjgl.util.glu.GLU.*;
import static org.lwjgl.opengl.GL11.*;

public class GameMain {
    public JFrame frame;
    public Canvas canvas;

    public boolean initialize(int width, int height) {
        try {
            Canvas canvas = new Canvas();
            JFrame frame = new JFrame("Open Rock Raiders - Delta");
            this.canvas = canvas;
            this.frame = frame;
            ComponentAdapter adapter = new ComponentAdapter() {
                public void componentResized(ComponentEvent e) {
                    resize();
                }
            };

            canvas.addComponentListener(adapter);
            canvas.setIgnoreRepaint(true);
            frame.setSize(640, 480);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.getContentPane().add(canvas);
            frame.setVisible(true);
            Dimension dim = this.canvas.getSize();

            Display.setLocation(100, 100);
            Display.setTitle("GL Window");
            Display.setDisplayMode(new DisplayMode(dim.width, dim.height));
            Display.setParent(canvas);
            Display.create();

            //openGL setup
            glViewport(0, 0, dim.width, dim.height);
            glMatrixMode(GL_PROJECTION);
            glLoadIdentity();
            gluPerspective(60.0f, (float)(dim.width/dim.height), 0.1f, 10000.0f);
            glMatrixMode(GL_MODELVIEW);
            glClearColor(94.0f/255.0f, 161.0f/255.0f, 255.0f/255.0f, 0.5f);
            glClearDepth(1.0);
            glShadeModel(GL_FLAT);
            glEnable(GL_DEPTH_TEST);
            glDepthFunc(GL_LEQUAL);
            glEnable(GL11.GL_CULL_FACE); 
            glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
            glEnable(GL_BLEND);
            glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        } catch (LWJGLException le) {
            le.printStackTrace();
        }
        return false;
    }

    public void resize()
    {
        Dimension dim = this.canvas.getSize();
        GL11.glViewport(0, 0, dim.width, dim.height);
    }
}
4

2 に答える 2

1

メインスレッドからすべての表示操作を行う必要があります。他の質問に投稿した例を見ると、新しいキャンバス サイズが保存され、メイン スレッドによって更新されていることがわかります。スレッドセーフでもあります。それを行う必要があり、グラフィックの初期化後に次のようなループが必要です。

while (!closeRequested) {
    GL11.glViewport(0, 0, dim.width, dim.height);
    Display.update();
}

//finished
Display.destroy();
于 2011-03-11T02:17:43.263 に答える
0

ほとんどの場合、opengl が初期化される前に最初のサイズ変更イベントを取得しています。canvas.addComponentListener(adapter);OpenGL セットアップの後に移動します。

于 2011-03-11T02:35:21.490 に答える