2011-12-20 8 views
1

私はOpenGlSurfaceViewでいくつかのプレーンを持っています。今私は飛行機に触れているかどうかを検出したい。私はstackoverflowやその他のフォーラムでいくつかのトピックを見つけましたが、どう対処するのか分かりません。多分誰も私を助けることができた。 SimplePlaneはメッシュが伸びるので、私はすべての私のメッシュのための独自のクラスを持っているOpenGLのタッチでセクション自身のオブジェクト

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

私の飛行機は、その構造の全てです。ここでは、メッシュクラスの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  

    } 

しかし、今、私はタッチを検出するために始めることができる方法がわかりません私の飛行機の。カラーピッキングやレイピッキングについて多くのことを読んでいますが、コードを実装する場所をどこから開始するのかはわかりません。

答えて

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クラスを取得する必要があります。 。

次は、最初にあなたのGLSurfaceViewにラッパーとしてそれを添付し、MatrixGrabberを使用する:

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点を与える。 *

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

私は「この最後のコードスニペットを:あなたは*、それを使用して線やカメラの目 "のポイントを作成し、光線は、ユーザーが選んだどのオブジェクトを取得するために交差あなたの3Dの世界でどのオブジェクトを検出することができます100%特定の作品はありませんM、しかし、真の解決策は、それ

編集のようなものになります。最後のコードスニペットを更新

+0

オーケーを今私は位置を取得します。しかし、現時点では、私はそれが正しい位置であるかどうかわからない。私はそれがよく見えると思う..しかし、私はどのように私の飛行機の中にpickPositionがあるかどうかを確認する必要がありますか? –

+0

gluUnprojectのxとyを 'x = mGLView.getWidth()/ 2'に変更し、' y = mGLView.getHeight()/ 2'を画面の中央に設定します。これはベクトル(0,0,1)=スクリーンの平面/平面に垂直になるはずです。ユーザーがクリックする場所にxを設定しますが、スクリーンの中心としてyを維持すると、x/z平面上にたくさんのベクトルが表示されます。また、 'gl.glDrawElements(GL10.GL_LINE_STRIPなど)'を使って、光線を画面に描画することもできます。あなたが周りを回転し始めるまで線がちょうど点か何かのように見えるならば、あなたは線に沿ってまっすぐに見ていて、ピッキングは動作しています –

+0

あなたのゲームは2Dだと思いますか? もしそうなら、あなたは 'GLU.gluProject' [1]を使って不正行為をすることができます。プレーンの4つの頂点のそれぞれのxとyのスクリーン座標を見つけるために使用します。 OnTouchListenerから取得した値を使用して、ユーザーがそのボックス内のどこかをクリックしたかどうかを確認できます。 [1]:http://developer.android.com/reference/android/opengl/GLU.html#gluProject%28float,%20float,%20float,%20float%5B%5D,%20int,%20float%5B %5D、%20int、%20int%5B%5D、%20int、%20float%5B%5D、%20int%29 –