OpenGLES - 在运行时创建对象

4

我刚开始学习OpenGL,从dev.android.com上的小教程入手。示例代码包括一个用于正方形图形的Square类。该对象将在onSurfaceCreated()方法中创建,并使用onDrawFrame()每帧绘制一次。以下是Square的示例代码(构造函数和绘图方法):

   public Square() {
    // initialize vertex byte buffer for shape coordinates

    ByteBuffer bb = ByteBuffer.allocateDirect(squareCoords.length * 4);
    bb.order(ByteOrder.nativeOrder());
    vertexBuffer = bb.asFloatBuffer();
    vertexBuffer.put(squareCoords);
    vertexBuffer.position(0);

    // initialize byte buffer for the draw list
    ByteBuffer dlb = ByteBuffer.allocateDirect(drawOrder.length * 2);
    dlb.order(ByteOrder.nativeOrder());
    drawListBuffer = dlb.asShortBuffer();
    drawListBuffer.put(drawOrder);
    drawListBuffer.position(0);

    // prepare shaders and OpenGL program
    int vertexShader = MyGLRenderer.loadShader(
            GLES20.GL_VERTEX_SHADER,
            vertexShaderCode);

    int fragmentShader = MyGLRenderer.loadShader(
            GLES20.GL_FRAGMENT_SHADER,
            fragmentShaderCode);

    mProgram = GLES20.glCreateProgram();             // create empty OpenGL Program
    GLES20.glAttachShader(mProgram, vertexShader);   // add the vertex shader to program
    GLES20.glAttachShader(mProgram, fragmentShader); // add the fragment shader to program
    GLES20.glLinkProgram(mProgram);                  // create OpenGL program executables
}


public void draw(float[] mvpMatrix) {
    // Add program to OpenGL environment
    GLES20.glUseProgram(mProgram);

    // get handle to vertex shader's vPosition member
    mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");

    // Enable a handle to the triangle vertices
    GLES20.glEnableVertexAttribArray(mPositionHandle);

    // Prepare the triangle coordinate data
    GLES20.glVertexAttribPointer(
            mPositionHandle, COORDS_PER_VERTEX,
            GLES20.GL_FLOAT, false,
            vertexStride, vertexBuffer);

    // get handle to fragment shader's vColor member
    mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");

    // Set color for drawing the triangle
    GLES20.glUniform4fv(mColorHandle, 1, color, 0);

    // get handle to shape's transformation matrix
    mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
    MyGLRenderer.checkGlError("glGetUniformLocation");

    // Apply the projection and view transformation
    GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
    MyGLRenderer.checkGlError("glUniformMatrix4fv");

    // Draw the square
    GLES20.glDrawElements(
            GLES20.GL_TRIANGLES, drawOrder.length,
            GLES20.GL_UNSIGNED_SHORT, drawListBuffer);

    // Disable vertex array
    GLES20.glDisableVertexAttribArray(mPositionHandle);
}

我的问题是:如何在触摸事件后创建对象,而不是在onSurfaceCreated()中创建对象?
我尝试定义一个Square变量,但在onSurfaceCreated()中不初始化它,然后在绘制之前检查对象是否为空。触摸后,我调用:
mSquare = new Square();

我知道这不是一个好的实现方式,但我只是想尝试一下它是否有效。我本来会创建一个可绘制元素列表,并在onDrawFrame()方法中运行它,从列表对象调用每个draw()。但由于这种方法会导致程序崩溃,我不知道该怎么办。

2个回答

5
您只能在OpenGL上下文中调用OpenGL。这个上下文有3个存在方法:
1)当上下文创建/重新创建时,会调用onSurfaceCreated方法——您应该在此处加载资源。
2)在创建后和表面大小调整后,会调用onSurfaceChanged方法——您应该在此处分配大小相关变量。
3)在此处执行渲染——您应该在此处执行所有绘图命令的onDrawFrame方法。
如果您尝试在上下文之外执行OpenGL调用,大多数情况下代码将无法正确执行。

感谢您的快速回答。那么,将布尔值与触摸事件一起更改,以便onDrawFrame方法创建对象,这是否是一个好的解决方案? - user3183627
最好在onDrawFrame之前预加载所有要使用的对象。在onTouchEvent中,您可能会更改一些参数(例如要显示哪些对象以及位置),而在onDrawFrame中,您将使用这些参数进行渲染。 - Sam

0

Android和GL上下文是不同的,并且它们以自己的方式在不同的线程上运行,因此如果您想在触摸屏上创建一个正方形,则必须像这样在GL上下文中创建对象

  1. http://pastebin.com/zAav7jpu

  2. 在触摸或您想要执行操作的位置初始化您的对象

    public static isAddedBody = false; //在touch_class中全局声明 public void touch(int.. whateva){ mSquare = new Square(); isAddedBody = true;

    }

在render()或draw()循环中

if (touch_class.isAddedBody){
  mSquare.createBody();
  touch_class.isAdded = false;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接