2011-12-20 27 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); 
    } 

:

내 비행기는 그 구조의 모든입니다.

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  

    } 

그러나이 지금은 내가 터치를 감지 시작할 수있는 방법을 모르는 내 렌더러의 onDrawFrame 방법이

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

을 그리고 그 다음은 당신은 메쉬 클래스의 그리기 방법을 볼 수 있습니다 내 비행기의. 색상 피킹이나 광선 피킹에 관해 많은 내용을 읽었지만, 코드를 구현하려면 어디에서 시작해야할지 모르겠습니다.

답변

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()에 필요한 행렬을 얻을 수 있습니다. 이 마지막 방법은 사용자가 터치 한 near plane (즉, z = near plane)에서 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]; 
      } 

* 나는 '이 마지막 코드 m 100 % 특정 작동하지만 실제 솔루션은

편집과 같이 보일 것입니다 : 마지막 코드 업데이트는

+0

좋아 지금은 내가 위치를 얻을 니펫을. 하지만 지금은 적절한 위치에있는 덩어리가 확실하지 않습니다. 나는 그것이 좋아 보인다라고 생각한다. 그러나 나는 picker가 나의 비행기의 내부에있다라고 wheter에게 점검해야한다? –

+0

gluUnproject의 x와 y를'x = mGLView.getWidth()/2'로 변경하고 y = mGLView.getHeight()/2, 즉 화면 중간으로 변경하십시오. 이것은 벡터 평면 (/ near plane)에 수직 인 벡터 (0,0,1) =를 생성해야합니다. 사용자가 클릭하는 위치로 x를 설정하고 화면 중심으로 y를 유지하면 x/z 평면에 많은 벡터가 있어야합니다. 또한'gl.glDrawElements (GL10.GL_LINE_STRIP, etc)'를 사용하여 화면에 광선을 그릴 수 있습니다. 당신이 선회를 시작할 때까지 선이 점이나 아무것도 보이지 않는다면 선을 따라 똑바로보고 피킹이 작동합니다 –

+0

또한 게임이 2D라고 가정합니까? 그렇다면'GLU.gluProject' [1]을 사용하여 속일 수 있습니다. 평면의 네 꼭지점 각각의 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 –

관련 문제