OpenGL ES 1.0:六色立方体自动旋转,但有些面丢失,无论我(取消)注释一些代码!

发布于 2024-10-22 00:34:18 字数 6257 浏览 2 评论 0原文

我正在尝试在 Android API 3 OpenGL(即 OpenGL ES 1.0)中构建一个每面一种不同颜色的立方体。 (我是OpenGL编程的初学者)。我设法让它以恒定的周期旋转,但最大的问题是我无法绘制所有的面。

丢失的面都不会相同。

  • 事实上,无论我使用还是
  • 不使用 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;

}

i am trying to build a one-different-color-per-face cube in Android API 3 OpenGL (so OpenGL ES 1.0). ( I am a beginner in OpenGL programming ). I managed to make it rotate in a constant period, but the big problem is that i can't manage to have all faces drawn.

Indeed, the missing face will not be the same whether

  • i rotate around x or y axis
  • i use or don't use the GL10#glEnable(GL10.GL_DEPTH_TEST) command in the method onSurfaceCreated

So, what is the simplest way to correct that ? (I have thought of using glClearDepth() and glCullFace(), without any success).

Here is the code of my class inherited from 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;

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

鼻尖触碰 2024-10-29 00:34:18

我认为你对矩阵堆栈的目的有点困惑。

投影应从世界空间中的固定位置映射到眼睛空间。

模型视图应该是相对于屏幕移动世界的所有事物的组合。因此,您通常会进行某种变换,根据您的世界内相机均匀地移动整个世界,然后对于世界中的每个对象,您将向模型视图附加一个额外的变换,以将其相对于世界放置。

深度测试的效果取决于投影矩阵最终的作用,因此这种混乱很可能导致您所描述的问题。

我建议而不是:

    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 在这里。这表示您需要透视投影,然后切换到模型视图并设置相机位置。

您通常也不会像代码那样无限期地累积模型视图上的旋转,因为数值错误会很快累积。但我敢打赌这只是一小段测试代码?

I think you have the purpose of the matrix stacks slightly confused.

Projection should map from a fixed position in world space to eye space.

Modelview should be the combination of everything that moves the world around relative to the screen. So, you'll typically have some sort of transform that moves the whole of the world equally depending on your in-world camera, then for each object in the world you'll append an additional transform to modelview to place it relative to the world.

The effect of depth testing depends on what the projection matrix ends up doing, so this confusion could well be causing the problems you describe.

I'd suggest that rather than:

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

You probably want something like:

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

See the documentation on gluPerspective here. That says that you want a perspective projection, then switches to modelview and sets up a camera position.

You also wouldn't normally just accumulate rotations on modelview indefinitely as your code does, because the numerical errors will accumulate quite quickly. But I'll wager that's just a quick bit of test code?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文