Android OpenGL ES добавляет объект на ощупь - PullRequest
1 голос
/ 30 октября 2011

Я создаю небольшое приложение для 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
}

}


OnDraw:

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

1 Ответ

1 голос
/ 30 октября 2011

Это не имеет никакого отношения к ландшафтному режиму, проблема в том, что вы переводите свой куб на -10 по оси z. Попробуйте поставить значения -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) и меньше, потому что следует за синими линиями к горизонту.

...