在Android OpenGL ES中创建3D道路

时间:2014-05-16 15:25:41

标签: android opengl-es 3d

我试图在Android中创建一个简单的游戏。通过公路我的意思是Temple RunSubway Surf这样的游戏,但更简单和抽象,所以我只能使用OpenGL ES而不需要任何其他库。 所以我已经阅读了许多解释3D构造逻辑的基本教程,并使用了创建旋转的3D立方体的基本示例。

我现在正尝试使用该示例来创建游戏之路。我让广场看起来更像一个矩形,并将其复制到30x5平方的道路上。我已经尝试了很多组合和互联网来寻找解决方案但我有这个问题\问题:

  1. 如何将所有30x5正方形设置为彼此相邻?我永远都是 让广场上有一些不必要的差距
  2. 我想将vieweye点("相机")设置为45度 在第一排的中间,所以玩家可以看到他的道路
  3. 接下来,我想沿着这条路走。所以,我见过旋转 以及它是如何工作的。有没有办法对观点或者做同样的事情 我是否需要更改绘制Z' s的方块?
  4. 我看到onDrawFrame()多次调用。至 控制FPS,我在互联网上看到人们使用过 有一个睡眠()自己的FPS计算。不是一个建成的 已经?
  5. GLRenderer代码:

    import javax.microedition.khronos.egl.EGLConfig;
    import javax.microedition.khronos.opengles.GL10;
    import android.content.Context;
    import android.opengl.GLSurfaceView;
    import android.opengl.GLU;
    import android.util.Log;
    
    
    class GLRenderer implements GLSurfaceView.Renderer {
    
        private static final String TAG = "GLRenderer" ;
        private final Context context;
    
        private float mCubeRotation = 70.0f;
        private Triangle triangle;
        private Cube[][] cube;
    
    
        GLRenderer(Context context) {
            this.context = context;
        }
        public void onSurfaceCreated(GL10 gl, EGLConfig config) {
            gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f); 
    
            gl.glClearDepthf(1.0f);
            gl.glEnable(GL10.GL_DEPTH_TEST);
            gl.glDepthFunc(GL10.GL_LEQUAL);
    
            gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT,GL10.GL_NICEST);
    
        }
        public void onSurfaceChanged(GL10 gl, int width, int height) {
            Log.d("MyOpenGLRenderer", "Surface changed. Width=" + width
                    + " Height=" + height);
            System.out.println("arg");
    
            //get map
            cube = new Cube[30][5];
            for(int i = 0; i < cube.length; i++)
                for(int j = 0; j < cube[i].length; j++)
                        cube[i][j] = new Cube();
    
            //draw triangle
            triangle = new Triangle(0.5f, 1, 0, 0);
    
            // Define the view frustum
            gl.glViewport(0, 0, width, height);
            gl.glMatrixMode(GL10.GL_PROJECTION);
            gl.glLoadIdentity();
            float ratio = (float) width / height;
            GLU.gluPerspective(gl, 45.0f, ratio, 0.1f, 100.0f);
    
            gl.glMatrixMode(GL10.GL_MODELVIEW);
            gl.glLoadIdentity();
    
        }
        public void onDrawFrame(GL10 gl) {
    
            // Clear the screen to black
            gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); 
    
    
            //translate(dx, dy, dz)
    
            // Position model so we can see it
            //gl.glMatrixMode(GL10.GL_MODELVIEW);
            gl.glLoadIdentity();
    
            gl.glTranslatef(0.0f, 0.0f, -10.0f);
            gl.glRotatef(mCubeRotation, 1.0f, 1.0f, 1.0f);
            gl.glTranslatef(0.0f, 0.0f, -10.0f);
            cube[0][0].draw(gl);
            gl.glTranslatef(0.0f, 0.0f, -10.0f);
            cube[0][1].draw(gl);
            gl.glTranslatef(0.0f, 0.0f, -10.0f);
            cube[0][2].draw(gl);
    
            gl.glLoadIdentity();                                    
    
            //set rotation
            mCubeRotation -= 0.15f;
            System.out.println("mCubeRotation: "+mCubeRotation);
    
        }
    }
    

    多维数据集代码:

    import java.nio.ByteBuffer;
    import java.nio.ByteOrder;
    import java.nio.FloatBuffer;
    
    import javax.microedition.khronos.opengles.GL10;
    
    class Cube {
    
        private FloatBuffer mVertexBuffer;  //vertex
        private FloatBuffer mColorBuffer;   //color 
        private ByteBuffer  mIndexBuffer;   //face indices
    
        float width  = 1.0f;
        float height = 0.5f;
        float depth  = 1.0f;
    
        private float vertices[] = { 
                             -width, -height, -depth, // 0
                              width, -height, -depth, // 1
                              width,  height, -depth, // 2
                             -width,  height, -depth, // 3
                             -width, -height,  depth, // 4
                              width, -height,  depth, // 5
                              width,  height,  depth, // 6
                             -width,  height,  depth, // 7
        };
    
        private float colors[] = {
                                   0.0f,  1.0f,  0.0f,
                                   1.0f,  0.0f,  1.0f,
                                   0.0f,  1.0f,  1.0f,
                                   0.5f,  0.0f,  1.0f,
                                   1.0f,  0.5f,  0.0f,
                                   1.0f,  1.0f,  0.0f,
                                   0.0f,  1.0f,  1.0f,
                                   0.0f,  0.0f,  1.0f,
                                   0.0f,  0.0f,  1.0f,
                                   1.0f,  1.0f,  0.0f,
                                   1.0f,  1.0f
                                };
    
        private byte indices[] = {
                                  0, 4, 5,
                                  0, 5, 1,
                                  1, 5, 6,
                                  1, 6, 2,
                                  2, 6, 7,
                                  2, 7, 3,
                                  3, 7, 4,
                                  3, 4, 0,
                                  4, 7, 6,
                                  4, 6, 5,
                                  3, 0, 1,
                                  3, 1, 2
                                  };
    
        public Cube() {
                ByteBuffer byteBuf = ByteBuffer.allocateDirect(vertices.length * 4);
                byteBuf.order(ByteOrder.nativeOrder());
                mVertexBuffer = byteBuf.asFloatBuffer();
                mVertexBuffer.put(vertices);
                mVertexBuffer.position(0);
    
                byteBuf = ByteBuffer.allocateDirect(colors.length * 4);
                byteBuf.order(ByteOrder.nativeOrder());
                mColorBuffer = byteBuf.asFloatBuffer();
                mColorBuffer.put(colors);
                mColorBuffer.position(0);
    
                mIndexBuffer = ByteBuffer.allocateDirect(indices.length);
                mIndexBuffer.put(indices);
                mIndexBuffer.position(0);
        }
    
        public void draw(GL10 gl) {             
                gl.glFrontFace(GL10.GL_CW);
    
                gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mVertexBuffer);
                gl.glColorPointer(4, GL10.GL_FLOAT, 0, mColorBuffer);
    
                gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
                gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
    
                gl.glDrawElements(GL10.GL_TRIANGLES, 36, GL10.GL_UNSIGNED_BYTE, 
                                mIndexBuffer);
    
                gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
                gl.glDisableClientState(GL10.GL_COLOR_ARRAY);
        }
    }
    

    最终我会使用glDrawArrays()或glDrawElements()绘制正方形数组,但现在我只使用了3个对象。

1 个答案:

答案 0 :(得分:0)

这里有很多问题。我无法详细介绍所有内容,但希望我能给你一些指导,引导你朝着正确的方向前进。

要绘制150个方格,您有多种选择:

  1. 使用单个正方形创建顶点缓冲区,并绘制150次,并应用平移。这可能是最容易让你离开的,所以我建议先让它运转起来。如果你的所有方块看起来都一样,这是一种合理的方法。
  2. 创建150个具有不同坐标的顶点缓冲区。我不推荐它,因为它效率最低,并且没有其他方法的任何好处。
  3. 将所有150个正方形的顶点存储在单个顶点缓冲区中。这将是前3个选项中效率最高的,但只有正方形的相对方向保持不变才能正常工作。一旦掌握了基础知识,您可能想尝试这个。
  4. 使用实例化渲染。这是一项更高级的功能,仅适用于ES 3.0。只需提及它以供将来参考。
  5. 您尝试的是选项1和2之间的混合。如果您想选择选项1,则只需要Cube类的一个实例。如果你看看你做了什么,这是有道理的。您创建了150个完全相同的对象,这些对象不是很有用。

    现在,关于你的问题:

    1. 要绘制没有间隙的正方形,您的翻译量必须与每个正方形的大小相同。您的方块宽2个单位,但每个单位翻译10个单位。你也可以在z方向上翻译它们,我不太明白。
    2. 如果您想坚持使用的功能,请查看GLU.gluLookAt()。它允许您将相机放在您想要的位置,并将其指向任何方向。
    3. 与2.每次想要移动视点时调用GLU.gluLookAt()
    4. Android将帧速率限制为每秒60帧。这通常是你应该拍摄的东西,恕我直言。如果你想将它限制在30 fps之后以节省电量,我认为你到达那里时可以越过那座桥。根据我最近研究的内容,在Android上没有干净,便携的方法。我看到的所提议的解决方案对我来说都很苛刻。
    5. 您的代码还需要做更多的事情:

      • 您的颜色定义看起来很奇怪。您可以指定4个组件中的颜色,并且数组的大小对此是正确的。但是你编写的数组每行有3个值,这使得它看起来像你想要3个组件颜色。任何一个都可以完成,但你需要确保你的一致性。除非您需要透明度,否则3个组件就足够了。
      • 您正在使用ES 1.0。这是有效的,可能更容易上手。但是你应该意识到它的许多功能都被认为是过时的,使用ES 2.0可以让你学习更多现代和当前的OpenGL功能。最初的障碍会更高,所以这里肯定会有一个权衡。