JOGLのグラフィクスのプログラムについての質問
以下のプログラミングコードについて質問です。以下のコードはJavaのJOGLで立方体を描くためのプログラムなのですが、これを編集して正四面体を描けるコードにかえたいです。どのように編集すればいいでしょうか?何行目のどこをどう書き換えるといいというようにできるだけ詳しくお願いします。
import java.awt.*;
import java.awt.event.*;
import javax.media.opengl.*;
import javax.media.opengl.glu.*;
import javax.media.opengl.awt.*;
public class CubePosition extends GLCanvas implements GLEventListener {
public static void main(String[] args) {
if (args.length == 3)
(new CubePosition("CubePosition", args)).showFrame();
else
(new CubePosition("CubePosition")).showFrame();
}
private Frame f;
protected GL2 gl;
protected GLU glu;
protected double eye_x = 4.0, eye_y = 3.0, eye_z = 7.0;
protected CubePosition(String name) {
super();
setSize(500, 500);
addGLEventListener(this);
f = new Frame(name);
f.add(this);
f.pack();
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
protected CubePosition(String name, String[] args) {
this(name);
eye_x = Double.parseDouble(args[0]);
eye_y = Double.parseDouble(args[1]);
eye_z = Double.parseDouble(args[2]);
}
protected void showFrame() {
f.setVisible(true);
}
public void init(GLAutoDrawable drawable) {
gl = drawable.getGL().getGL2();
glu = new GLU();
gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
gl.glEnable(GL2.GL_DEPTH_TEST);
gl.glEnable(GL2.GL_CULL_FACE);
}
public void reshape(GLAutoDrawable drawable,
int x, int y, int w, int h) {
final double fieldOfView = 25.0, near = 1.0, far = 20.0;
double aspect = (double) w / (double) h;
gl.glViewport(0, 0, w, h);
gl.glMatrixMode(GL2.GL_PROJECTION);
gl.glLoadIdentity();
glu.gluPerspective(fieldOfView, aspect, near, far);
gl.glMatrixMode(GL2.GL_MODELVIEW);
gl.glLoadIdentity();
glu.gluLookAt(eye_x, eye_y, eye_z, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
}
public void diplay(GLAutoDrawable drawable) {
gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
cubeDisplay();
}
static float[][] vertices =
{{ -1.0f, -1.0f, -1.0f },{ 1.0f, -1.0f, -1.0f },{ 1.0f, 1.0f, -1.0f },
{ -1.0f, 1.0f, -1.0f },{-1.0f, -1.0f, 1.0f },{ 1.0f, -1.0f, 1.0f},
{ 1.0f, 1.0f, 1.0f },{ -1.0f, 1.0f, 1.0f }};
static int[][] faces =
{{ 1, 2, 6, 5 },{ 2, 3, 7, 6 },{ 4, 5, 6, 7 },{ 0, 4, 7, 3 },
{ 0, 1, 5, 4 },{ 0, 3, 2, 1 }};
static float[][] colors =
{{ 0.0f, 1.0f, 1.0f },{ 1.0f, 0.0f, 1.0f },{ 1.0f, 1.0f, 0.0f },
{ 0.0f, 0.5f, 0.5f },{ 0.5f, 0.0f, 0.5f },{ 0.5f, 0.5f, 0.0f }};
protected void cubeDisplay() {
gl.glBegin(GL2.GL_QUADS);
for (int i =0; i < faces.length; i++) {
gl.glColor3fv(colors[i], 0);
for (int j = 0; j < faces[i].length; j++)
gl.glVertex3fv(vertices[faces[i][j]], 0);
}
gl.glEnd();
gl.glFlush();
}
public void dispose(GLAutoDrawable drawable) {
}
}
補足
>GLクラスのオブジェクトは描画時に都度作成されるため、例えばGLJPanel.display()内でGLクラスのオブジェクトをメンバ変数か何かに保持したとしても、その変数を使ってOpenGLの機能を呼ぶことはできません。 間違ってました。display等はGLEventListenerのメソッドでした。 GLクラスを変数に保存して使っても、それをほかのクラスに渡さずに使う分には問題ないようです。(でも全てのメソッドでGLDrawableを渡しているのは、違うインスタンスが渡されることもあるという事なんでしょうか・・?) その後、一応表示はできるようになりましたが、これがベストの方法ではないと思います。 描画ライブラリの処理が実行されているスレッドとGLJPanelの処理が実行されているスレッドが別なのに気づいたので、GLDrawable.createContextで、コンテキストを複製して、ライブラリが実行されているスレッドでGLContext.makeCurrentを呼び出しました。(C++でOpenGLを使っていたときの経験で、ひとつのコンテキストを二つ以上のスレッドで有効にすることは出来ないというのは知っていました。)しかし、このメソッドを呼び出したときに例外が発生してしまいます。 Exception in thread "Thread-0" javax.media.opengl.GLException:wglShareLists(0x40000, 0x10001) failed: error code 0 Object.waitを使って、GLEventListener.initが完了するまで待つようにしはしたんですが・・。それで、makeCurrentの前に500msぐらいThread.Sleepで待つと、うまく行くこともあります。しかしもっと他にいい方法が無いものでしょうか。 ユーザーが自作したクラスにGLJPanel(GLEventListener?)を継承するのを強制させるのが駄目なのは、他のAPIを使った描画も利用できるようにする予定なのに、それだとJOGLべったりになってしまうからです。携帯だとJOGLは使えないので。