1

我的 OpenGLSurfaceView 上有几架飞机。现在我想检测飞机是否被触摸。我在 stackoverflow 和其他论坛上发现了一些主题,但我不知道如何处理它们。也许任何人都可以帮助我。

我的飞机都是这样的结构:

public SimplePlane() {
        float textureCoordinates[] = { 
                0.0f, 1.0f, //
                1.0f, 1.0f, //
                0.0f, 0.0f, //
                1.0f, 0.0f, //
        };

        short[] indices = new short[] { 
                0, 1, 
                2, 1, 
                3, 2 };

        float[] vertices = new float[] { 
                -0.5f, -0.5f, 0.0f, 
                0.5f, -0.5f, 0.0f,
                -0.5f, 0.5f, 0.0f, 
                0.5f, 0.5f, 0.0f };

        setIndices(indices);
        setVertices(vertices);
        setTextureCoordinates(textureCoordinates);
    }

我的所有网格都有一个自己的类,所以 SimplePlane 扩展了网格。这里可以看到Mesh类中的draw方法:

public void draw(GL10 gl) {

        gl.glFrontFace(GL10.GL_CCW);
        gl.glEnable(GL10.GL_CULL_FACE);
        gl.glCullFace(GL10.GL_BACK);

        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, verticesBuffer);
        gl.glColor4f(rgba[0], rgba[1], rgba[2], rgba[3]);
        if (colorBuffer != null) {
            gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
            gl.glColorPointer(4, GL10.GL_FLOAT, 0, colorBuffer);
        }

        if (mShouldLoadTexture) {
            loadGLTexture(gl);
            mShouldLoadTexture = false;
        }
        if (mTextureId != -1 && mTextureBuffer != null) {
            gl.glEnable(GL10.GL_TEXTURE_2D);
            gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

            gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mTextureBuffer);
            gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureId);
        }


        gl.glRotatef(rx, 1, 0, 0);
        gl.glRotatef(ry, 0, 1, 0);
        gl.glRotatef(rz, 0, 0, 1);

        gl.glTranslatef(x, y, z);

        gl.glDrawElements(GL10.GL_TRIANGLES, numOfIndices,
                GL10.GL_UNSIGNED_SHORT, indicesBuffer);
        gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
        if (mTextureId != -1 && mTextureBuffer != null) {
            gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
        }

        gl.glDisable(GL10.GL_CULL_FACE);
    }

我的渲染器的 onDrawFrame 方法:

public void onDrawFrame(GL10 gl) {
        gl.glClearColor(_red, _green, _blue, 0.0f);
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

        GLU.gluLookAt(gl, 0,0,0,    0,0,0,   0,0,0);        

        gl.glLoadIdentity();    
        gl.glRotatef(_ry, 0f, 1f, 0f);

        root.draw(gl);  // a group of meshes    

    }

但现在我不知道如何才能开始检测到我的飞机的触摸。我阅读了很多关于颜色拾取或光线拾取的内容,但我不知道我应该从我的代码中从哪里开始来实现它。

4

1 回答 1

1

首先使用myGLSurfaceView.setOnTouchListener(new MyOnTouchListener())(myOnTouchListener 实现OnTouchListener的地方)获取用户在屏幕上触摸的点。

然后您需要从 API 演示 (C:\android-sdk\samples\android-7\ApiDemos\src\com\example\android\apis\graphics\spritetext) 中获取 MatrixGrabber、MatrixStack、MatrixTracking 类。

接下来,要使用 MatrixGrabber,首先将其作为包装器附加到您的 GLSurfaceView:

public class GraphicsEngine extends Activity {
protected GLSurfaceView mGLView;
protected GraphicsRenderer graphicsRenderer;

/** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.graphics);

        graphicsRenderer = new GraphicsRenderer(this);

        mGLView = (GLSurfaceView) findViewById(R.id.graphics_glsurfaceview1);

        // ------
        // THIS BIT HERE
        mGLView.setGLWrapper(new GLSurfaceView.GLWrapper() {
        public GL wrap(GL gl) {
            return new MatrixTrackingGL(gl);
        }});
        // ------


        mGLView.setEGLConfigChooser(true);         
        mGLView.setRenderer(graphicsRenderer);

}

然后您可以获得GLU.gluUnProject()所需的矩阵。最后一种方法为您提供用户触摸的近平面(即 z = 近平面)上的 3D 点。您可以使用它和相机的“眼睛”点创建射线,然后检测 3D 世界中的哪些物体与射线相交以获得用户拾取的物体*:

    MatrixGrabber matrixGrabber = new MatrixGrabber();
    matrixGrabber.getCurrentModelView(gl);  
    matrixGrabber.getCurrentProjection(gl);

    float[] vector = new float[4]; 

    // x and y come from the x/y you get from the OnTouchListener. 
    // OpenGL works from the bottom left corner, so flip the y
    GLU.gluUnProject(x, mGLView.getHeight()-y, 0.9f, matrixGrabber.mModelView, 0, matrixGrabber.mProjection, 0, new int[]{mGLView.getTop(),mGLView.getLeft(),mGLView.getWidth(),mGLView.getHeight()}, 0, vector, 0);

    Vector3f pickPosition = new Vector3f();
            if(vector[3]!=0){
                pickPosition.x = vector[0] / vector[3];
                pickPosition.y = vector[1] / vector[3];
                pickPosition.z = vector[2] / vector[3];
            }

*最后一个代码片段我不是 100% 确定有效,但真正的解决方案看起来像它

编辑:更新了最后的代码片段

于 2011-12-20T14:41:48.430 回答