1

Android API 3 OpenGL (OpenGL ES 1.0) で、面ごとに 1 つの異なる色のキューブを構築しようとしています。(私は OpenGL プログラミングの初心者です)。一定周期で回転させることはできましたが、大きな問題は、すべての顔を描くことができないことです。

実際、欠落している顔は同じではありません。

  • x軸またはy軸を中心に回転します
  • メソッド onSurfaceCreated で GL10#glEnable(GL10.GL_DEPTH_TEST) コマンドを使用するか使用しないか

それで、それを修正する最も簡単な方法は何ですか?(私は glClearDepth() と glCullFace() を使用することを考えましたが、成功しませんでした)。

GLSurfaceView.Renderer から継承したクラスのコードは次のとおりです。

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.opengl.GLU;
import android.opengl.GLSurfaceView.Renderer;

public class MyGLRenderer implements Renderer {

    public MyGLRenderer(){
        buildCubeBuffers();
    }

    @Override
    public void onDrawFrame(GL10 gl) {
        gl.glRotatef(0.6f, 1.0f, 0.0f, 0.0f);
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

        gl.glVertexPointer(COORDS_PER_VERTEX, GL10.GL_FLOAT, 0, cubeBuffer);
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        //--- FRONT
        gl.glColor4f(1.0f, 0.0f, 0.0f, 0.0f); //RED
        gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, VERTICES_NUMBER);
        //--- RIGHT
        gl.glColor4f(0.0f, 1.0f, 0.0f, 0.0f); // GREEN
        gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 4, VERTICES_NUMBER);
        //--- BACK
        gl.glColor4f(0.0f, 0.0f, 1.0f, 0.0f); // BLUE
        gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 8, VERTICES_NUMBER);
        //--- LEFT
        gl.glColor4f(1.0f, 1.0f, 0.0f, 0.0f); // YELLOW
        gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 12, VERTICES_NUMBER);
        //--- TOP
        gl.glColor4f(1.0f, 0.5f, 0.0f, 0.0f); // ORANGE
        gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 16, VERTICES_NUMBER);
        //--- BOTTOM
        gl.glColor4f(1.0f, 0.0f, 1.0f, 0.0f); // PURPLE 
        gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 20, VERTICES_NUMBER);
        //--
        gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        if (height == 0) height = 1;
        if (width < height)
            gl.glViewport(0, 0, width, width);
        else
            gl.glViewport(0, 0, height, height);

        gl.glMatrixMode(GL10.GL_PROJECTION);
        gl.glLoadIdentity();
        GLU.gluLookAt(gl, 0.0f, 0.0f, 3.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);

        gl.glMatrixMode(GL10.GL_MODELVIEW);
        gl.glLoadIdentity();
    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        gl.glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
        //////////////////////////////////////
        /*
         * If i comment next line :
         * => Rotation on y axis
         * yellow face is visible, red face is invisible
         * Otherwise : yellow invisible and red visible !!!
         * => Rotation on x axis
         * purple face is visible, red face is invisible
         * Otherwise : purple invisible and red visible !!!
         * Why ???
         */
        //////////////////////////////////////
        gl.glEnable(GL10.GL_DEPTH_TEST);
    }

    private void buildCubeBuffers(){
        final float cubeVertices[] = {
            // front
            -CUBE_UNITY_COORD, +CUBE_UNITY_COORD, +CUBE_UNITY_COORD, // point 0 : Left-Top-Front
            +CUBE_UNITY_COORD, +CUBE_UNITY_COORD, +CUBE_UNITY_COORD, // point 1 : Right-Top-Front
            -CUBE_UNITY_COORD, -CUBE_UNITY_COORD, +CUBE_UNITY_COORD, // point 3 : Left-Bottom-Front
            +CUBE_UNITY_COORD, -CUBE_UNITY_COORD, +CUBE_UNITY_COORD, // point 2 : Right-Bottom-Front
            // right
            +CUBE_UNITY_COORD, +CUBE_UNITY_COORD, +CUBE_UNITY_COORD, // point 1 : Right-Top-Front
            +CUBE_UNITY_COORD, +CUBE_UNITY_COORD, -CUBE_UNITY_COORD, // point 5 : Right-Top-Back
            +CUBE_UNITY_COORD, -CUBE_UNITY_COORD, +CUBE_UNITY_COORD, // point 2 : Right-Bottom-Front
            +CUBE_UNITY_COORD, -CUBE_UNITY_COORD, -CUBE_UNITY_COORD, // point 6 : Right-Bottom-Back
            // back
            +CUBE_UNITY_COORD, +CUBE_UNITY_COORD, -CUBE_UNITY_COORD, // point 5 : Right-Top-Back
            -CUBE_UNITY_COORD, +CUBE_UNITY_COORD, -CUBE_UNITY_COORD, // point 4 : Left-Top-Back
            +CUBE_UNITY_COORD, -CUBE_UNITY_COORD, -CUBE_UNITY_COORD, // point 6 : Right-Bottom-Back
            -CUBE_UNITY_COORD, -CUBE_UNITY_COORD, -CUBE_UNITY_COORD, // point 7 : Left-Bottom-Back
            // left
            -CUBE_UNITY_COORD, +CUBE_UNITY_COORD, -CUBE_UNITY_COORD, // point 4 : Left-Top-Back
            -CUBE_UNITY_COORD, +CUBE_UNITY_COORD, +CUBE_UNITY_COORD, // point 0 : Left-Top-Front
            -CUBE_UNITY_COORD, -CUBE_UNITY_COORD, -CUBE_UNITY_COORD, // point 7 : Left-Bottom-Back
            -CUBE_UNITY_COORD, -CUBE_UNITY_COORD, +CUBE_UNITY_COORD, // point 3 : Left-Bottom-Front
            // top
            -CUBE_UNITY_COORD, +CUBE_UNITY_COORD, -CUBE_UNITY_COORD, // point 4 : Left-Top-Back
            +CUBE_UNITY_COORD, +CUBE_UNITY_COORD, -CUBE_UNITY_COORD, // point 5 : Right-Top-Back
            -CUBE_UNITY_COORD, +CUBE_UNITY_COORD, +CUBE_UNITY_COORD, // point 0 : Left-Top-Front
            +CUBE_UNITY_COORD, +CUBE_UNITY_COORD, +CUBE_UNITY_COORD, // point 1 : Right-Top-Front
            // bottom
            -CUBE_UNITY_COORD, -CUBE_UNITY_COORD, +CUBE_UNITY_COORD, // point 3 : Left-Bottom-Front
            +CUBE_UNITY_COORD, -CUBE_UNITY_COORD, +CUBE_UNITY_COORD, // point 2 : Right-Bottom-Front
            -CUBE_UNITY_COORD, -CUBE_UNITY_COORD, -CUBE_UNITY_COORD, // point 7 : Left-Bottom-Back
            +CUBE_UNITY_COORD, -CUBE_UNITY_COORD, -CUBE_UNITY_COORD, // point 6 : Right-Bottom-Back
        };
        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(cubeVertices.length * FLOAT_CAPACITY_BYTES);
        byteBuffer.order(ByteOrder.nativeOrder());
        cubeBuffer = byteBuffer.asFloatBuffer();
        cubeBuffer.put(cubeVertices);
        cubeBuffer.rewind();
    }

    private final static float CUBE_UNITY_COORD = 0.5f;
    private static FloatBuffer cubeBuffer;

    private final static int FLOAT_CAPACITY_BYTES = 4;
    private final static int COORDS_PER_VERTEX = 3;
    private final static int VERTICES_NUMBER = 4;

}
4

1 に答える 1

1

マトリックススタックの目的が少し混乱していると思います。

投影は、ワールド空間の固定位置から目の空間にマッピングする必要があります。

Modelview は、画面に対して世界を動かすすべてのものの組み合わせである必要があります。したがって、通常は、インワールド カメラに応じて世界全体を均等に移動するある種の変換を行います。次に、世界の各オブジェクトに対して、モデルビューに追加の変換を追加して、世界に対して相対的に配置します。 .

深度テストの効果は、射影行列が最終的に何をするかに依存するため、この混乱があなたが説明する問題を引き起こしている可能性があります。

ではなく、次のことをお勧めします。

    gl.glMatrixMode(GL10.GL_PROJECTION);
    gl.glLoadIdentity();
    GLU.gluLookAt(gl, 0.0f, 0.0f, 3.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);

    gl.glMatrixMode(GL10.GL_MODELVIEW);
    gl.glLoadIdentity();

おそらく次のようなものが必要です。

    gl.glMatrixMode(GL10.GL_PROJECTION);
    gl.glLoadIdentity();
    GLU.gluPerspective(something suitable);

    gl.glMatrixMode(GL10.GL_MODELVIEW);
    gl.glLoadIdentity();
    GLU.gluLookAt(gl, 0.0f, 0.0f, 3.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);

gluPerspectiveに関するドキュメントはこちらを参照してください。これは、透視投影が必要であることを示しており、モデルビューに切り替えてカメラの位置を設定します。

また、数値エラーは非常に急速に蓄積されるため、通常、コードのように無期限にモデルビューに回転を蓄積することはありません。しかし、これはほんの少しのテスト コードに過ぎないと思いますか?

于 2011-03-17T01:25:28.880 に答える