Android OpenGL ES 触摸添加对象

标签 android opengl-es touch coordinates

我正在构建一个小型 Android 应用程序,它将在用户触摸时添加一个立方体。 z 深度始终为 -10,屏幕始终处于横向模式。这个问题好像被问过很多次了,但是我跑不起来,原谅我是opengl的新手。 我对与 gluUnproject 一起使用的屏幕坐标/窗口坐标/对象坐标感到很困惑。据我了解,屏幕是用户触摸时,我们甚至从运动中获得 x 和 y。窗口坐标是我们加载身份的时候,对象坐标是我们转换单位矩阵得到对象坐标的时候。是吗?

这是我的代码,矩阵堆叠来自 android api 示例。请指出我做错了什么。


绘图部分:

public void draw(GL10 gl) {
    for (GLObject glObject : list) {
        if (glObject != null) {
            gl.glLoadIdentity();
            glObject.draw(gl);
        }
    }
    gl.glMatrixMode(GL10.GL_MODELVIEW);
    gl.glLoadIdentity();
    if (isTouching) {
        boolean addObject = false;
        for (GLObject glObject : list) {
            addObject = glObject.checkTouch(gl, x, y);
        }
        if (!addObject) {
            i++;
            Log.d("i", i + "");
            addGLObject(gl);
        }
        isTouching = false;
    }
}

这是添加对象的代码

private void getMatrix(GL10 gl, int mode, float[] mat) {
    GLView.matrixTrackingGL.glMatrixMode(mode);
    GLView.matrixTrackingGL.getMatrix(mat, 0);
}
public void addGLObject(GL10 gl) {
    float[] XY = getWorldCoordinate(gl, x, y);

    if (XY != null) {
//          XY[0] = (float) (x - Main.SCREEN_WIDTH / 2) / 10;
//
//          XY[1] = (float) (Main.SCREEN_HEIGHT / 2 - y) / 10;

        GLObject glObject = new GLObject(colors, XY[0], XY[1]);
        Log.d("Object position", "X: " + XY[0] + " Y: " + XY[1]);
        list.add(glObject);
    }
}
private float[] getWorldCoordinate(GL10 gl, int x, int y) {
    float[] modelMatrix = new float[16];
    float[] projMatrix = new float[16];
    int[] viewport = {0, 0, Main.SCREEN_WIDTH, Main.SCREEN_HEIGHT};


    getMatrix(gl, GL10.GL_MODELVIEW, modelMatrix);
    getMatrix(gl, GL10.GL_PROJECTION, projMatrix);

    float[] output = new float[4];
    GLU.gluUnProject(x, viewport[1] + viewport[3] - y, -10, modelMatrix, 0, projMatrix, 0, viewport, 0, output, 0);
    return new float[] {output[0]/output[3], output[1]/output[3]};
}

public class GLObject {
    private float[] vertices = { 1.000000f, 1.000000f, -1.000000f, 1.000000f,
    -1.000000f, -1.000000f, -1.000000f, -1.000000f, -1.000000f,
    -1.000000f, 1.000000f, -1.000000f, 1.000000f, 1.000000f, 1.000000f,
    1.000000f, -1.000001f, 1.000000f, -1.000000f, -1.000000f,
    1.000000f, -1.000000f, 1.000000f, 1.000000f, };
private short[] faces = { 0, 1, 2, 0, 2, 3, 4, 7, 6, 4, 6, 5, 0, 4, 5, 0,
    5, 1, 1, 5, 6, 1, 6, 2, 2, 6, 7, 2, 7, 3, 4, 0, 3, 4, 3, 7 };
private float[] colors;
private float[] rot = { 0.0f, 0.0f, 0.0f };
private Float positionX, positionY;
private int alpha = 0;

// Our vertex buffer.
private FloatBuffer vertexBuffer;

// Our index buffer.
private ShortBuffer faceBuffer;

public GLObject() {
    init();
}

public GLObject(float[] colors, float x, float y) {
    this.colors = colors.clone();
    this.positionX = x;
    this.positionY = y;

    if (positionX.intValue() % 2 == 0) {
        rot[0] = 1.0f;
    } else {
        if (positionY.intValue() % 2 == 0) {
    rot[1] = 1.0f;
    } else {
        rot[2] = 1.0f;
    }
    }
    init();
}

private void init() {
    ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
    vbb.order(ByteOrder.nativeOrder());
    vertexBuffer = vbb.asFloatBuffer();
    vertexBuffer.put(vertices);
    vertexBuffer.position(0);

    ByteBuffer ibb = ByteBuffer.allocateDirect(faces.length * 2);
    ibb.order(ByteOrder.nativeOrder());
    faceBuffer = ibb.asShortBuffer();
    faceBuffer.put(faces);
    faceBuffer.position(0);
}

public boolean checkTouch(GL10 gl, int x, int y) {
    boolean isTouched = false;
    ByteBuffer pixels = ByteBuffer.allocate(4);

    gl.glReadPixels(x, Main.SCREEN_HEIGHT - y, 1, 1, GL10.GL_RGBA,
            GL10.GL_UNSIGNED_BYTE, pixels);
    Log.d("COLOR",
            pixels.get(0) + " " + pixels.get(1) + " " + pixels.get(2) + " "
                    + pixels.get(3));
            // isTouched always false to test always add object to screen
    return isTouched;
}

public void draw(GL10 gl) {
    // Counter-clockwise winding.
    gl.glFrontFace(GL10.GL_CCW); // OpenGL docs
    // Enable face culling.
    gl.glEnable(GL10.GL_CULL_FACE); // OpenGL docs
    // What faces to remove with the face culling.
    gl.glCullFace(GL10.GL_BACK); // OpenGL docs

    // Enabled the vertices buffer for writing and to be used during
    // rendering.
    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);// OpenGL docs.
    // Enable color
    gl.glColor4f(colors[0], colors[1], colors[2], 1.0f);
    // Specifies the location and data format of an array of vertex
    // coordinates to use when rendering.
    gl.glPushMatrix();
    gl.glTranslatef(positionX, positionY, -10);
    // rotate
    alpha += 1;
    gl.glRotatef(alpha, rot[0], rot[1], rot[2]);
    // draw
    gl.glVertexPointer(3, GL10.GL_FLOAT, 0, // OpenGL docs
            vertexBuffer);

    gl.glDrawElements(GL10.GL_TRIANGLES, faces.length,// OpenGL docs
            GL10.GL_UNSIGNED_SHORT, faceBuffer);
    gl.glPopMatrix();
    // Disable the vertices buffer.
    gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); // OpenGL docs
    // Disable face culling.
    gl.glDisable(GL10.GL_CULL_FACE); // OpenGL docs
}


绘制:

public void onDrawFrame(GL10 gl) {
        // TODO Auto-generated method stub
        // Clears the screen and depth buffer.
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | // OpenGL docs.
                GL10.GL_DEPTH_BUFFER_BIT);
        gl.glMatrixMode(GL10.GL_PROJECTION);
        // Reset the projection matrix
        gl.glLoadIdentity();
        GLU.gluPerspective(gl, 90.0f, Main.SCREEN_WIDTH/Main.SCREEN_HEIGHT, 3.0f, 100.0f); 
        gl.glMatrixMode(GL10.GL_MODELVIEW);
        gl.glLoadIdentity();
        GLU.gluLookAt(gl, 4.0f, 2.0f, 1.0f, 
                0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);    
        // draw object
        glObjectManager.draw(gl);
    }

最佳答案

这与横向模式无关,问题是您在 z 轴上将立方体平移了 -10。尝试输入 -100 的值,所有立方体都将位于中心。然后尝试将 0 作为 z 值 (x, y, 0)。立方体将离屏幕中心更远,更接近您期望的位置。

http://tle.tafevc.com.au/toolbox/file/9495cce8-17b5-a8a5-d9b3-47c0c142d88d/1/sketches_and_drawings_lo.zip/3204a_20_reading_drawings/images/brick_perspective.jpg透视投影的例子。当立方体位于 z=0 时,这就是图像中的内容。但是当 z=-10 时,它更靠近屏幕中心 (X) 并且更小,因为它沿着蓝线延伸到地平线。

关于Android OpenGL ES 触摸添加对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7943264/

相关文章:

android - 如何在android中创建透明的圆形按钮?

未指定 Android SDK

ios - Shader中生成Float Texture和使用

opengl-es - 跨步在OpenGL | ES中是什么意思

java - 具有多个 View 的 Android 触摸事件

android - 无法解析 Java8、Android Studio 中的符号 'LocalDateTime'

android - 尝试使用 SharedPreferences 存储字符串集时的不当行为

javascript - 使用两个或多个具有不同数量属性的着色器时发生冲突

java - android触摸输入错误

javascript - 是否有模拟触摸事件的附加组件或扩展?