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

最初に、( myOnTouchListener がOnTouchListenermyGLSurfaceView.setOnTouchListener(new MyOnTouchListener())を実装する)を使用して、ユーザーが画面に触れたポイントを取得します。

次に、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 に答える