2012-03-07 4 views
1

Ive는 min3d를 사용하여 광선 피킹을 구현했으며 온라인에서 찾은 일부 코드를 구현했지만 구현했을 때 약간의 시간이 지나면 한 상자를 잘못 클릭 할 때가 있음을 알게되었습니다. 하나는 고르다. 때로는 화면에 심지어 선택하지 않습니다. 이제OpenGl ES에서 광선 피킹 코드

private void rayPicking(float x, float y) 
{ 
    //intersection with near plane 
    float[] near = new float[4]; 
    GLU.gluUnProject(x, scene.getViewport()[3] - y, 0f, scene.getGrabber().mModelView, 0, scene.getGrabber().mProjection, 0, scene.getViewport(), 0, near, 0); 
    if (near[3] != 0) 
    { 
     near[0] = near[0]/near[3]; 
     near[1] = near[1]/near[3]; 
     near[2] = near[2]/near[3]; 
    } 
    Number3d near3 = new Number3d(near[0], near[1], near[2]); 

    //and far plane 
    float[] far = new float[4]; 
    GLU.gluUnProject(x, scene.getViewport()[3] - y, 1f, scene.getGrabber().mModelView, 0, scene.getGrabber().mProjection, 0, scene.getViewport(), 0, far, 0); 
    if (far[3] != 0) 
    { 
     far[0] = far[0]/far[3]; 
     far[1] = far[1]/far[3]; 
     far[2] = far[2]/far[3]; 
    } 
    Number3d far3 = new Number3d(far[0], far[1], far[2]); 

    Box firstPicked = null; 
    Box currentModel = null; 
    Number3d currentCoords = null; 
    Number3d firstPickedCoords = new Number3d(); 

if (!sceneBoxes.isEmpty()) 
{ 
    //here we check each model if it was tapped and if several models were tapped, we take only that which is closer to the near clipping plane 
    Iterator<Box> itr = sceneBoxes.iterator(); 
    while (itr.hasNext()) 
    { 
     currentModel = itr.next(); 
     currentCoords = new Number3d(currentModel.position().x, currentModel.position().y, currentModel.position().z); 
     if (picked (far3, near3, currentCoords, 1.2f)) 
      if (firstPicked==null) 
       { 
        firstPicked = currentModel; 
        firstPickedCoords.setAllFrom(currentCoords); 
       } 
      else if (Number3d.add(currentCoords, near3).length() < Number3d.add(firstPickedCoords, near3).length()) 
       { 
        firstPicked = currentModel; 
        firstPickedCoords.setAllFrom(currentCoords); 
       } 
    } 
} 

    if (firstPicked != null) // if model picked 
    { 
     String temp = firstPicked.getTitle(); 
     String temp2 = firstPicked.getLink(); 
     Log.w("3d touch working "+temp, "3d touch working "+temp); 
     Intent intent = new Intent(CurAct.this, WebViewer.class); 
     intent.putExtra("clkURL", temp2); 
     intent.putExtra("clkUID", curr_uid); 
     intent.putExtra("rid", curr_rid); 
     startActivity(intent); 

     firstPicked = null; 
     temp = null; 
     temp2 = null; 

    } 
} 

private boolean picked(Number3d a, Number3d b, Number3d q, float r) 
{ 
    float ab = (float) Math.sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+(a.z-b.z)*(a.z-b.z)); 
    float aq = (float) Math.sqrt((a.x-q.x)*(a.x-q.x)+(a.y-q.y)*(a.y-q.y)+(a.z-q.z)*(a.z-q.z)); 
    float bq = (float) Math.sqrt((b.x-q.x)*(b.x-q.x)+(b.y-q.y)*(b.y-q.y)+(b.z-q.z)*(b.z-q.z)); 

    float p = (ab + aq + bq)/2; 

    float hh = (float) Math.sqrt(p * (p - ab) * (p - aq) * (p - bq)); 
    float h; 
    if (ab!=0) h = 2 * hh/ab; else h = 2*hh; 

    if (aq<h) h = aq; 
    if (bq<h) h = bq; 

    if (h<r)return true; else return false; 
} 

나는 또한 컬링하지만 길 아래 때문에이 일을 느려 ​​수행하는 데 프러스 텀을 구현하는 시도 :이 코드의 꽤 첫 번째 장소에서 구현 얻을하지만 전화의 주요 두 가지 방법은 다음과 같습니다했다 나는 그것을 최적화하기 위해 많은 것을 할 필요가 없다. 그러나 어떤 사람이 보일 수도 있고, 어쩌면 나를 더 정확하게 만들 수있는 방법에 대한 조언을 해줄 수 있다면. 내가 피킹 방법이라고 부르는 곳. 당신이 충돌 감지에 실수를하는 것처럼 당신이 버그는 소리

_glSurfaceView.setOnTouchListener( 
     new View.OnTouchListener() { 

      @Override 
      public boolean onTouch(View arg0, MotionEvent e) { 

       switch (e.getAction() & MotionEvent.ACTION_MASK) 
       { 
        case MotionEvent.ACTION_DOWN: 
         startX = e.getX(); 
         startY = e.getY(); 
         trace = 0.0f; 
         time = System.currentTimeMillis(); 
         touchMode = DRAG; 
        break; 

        case MotionEvent.ACTION_UP: 
         // we use ray picking only when the tap wasn't longer than 0.5 sec and if we almost didn't move our finger 
         //Log.w("this is touch y"+e.getY()+" viewport is"+scene.getViewport()[3], "this is touch x"+e.getX()); 
         if ((System.currentTimeMillis()-time < 500) && (trace<scene.getViewport()[3]*0.075)) rayPicking(e.getX(), e.getY()); 
         time = 0; 

        case MotionEvent.ACTION_POINTER_UP: 
         touchMode = NONE; 
        break; 
       } 
       return true; 

      } 
      } 
     ); 

답변

2

가 나는 점 제품에 있던 기능에 버그가 있었고, 정말 이상한 결과가 발생했습니다. 충돌 알고리즘을 더 게시 할 수 있습니까?

여기에서 광선 피킹을 구현했습니다. http://android-raypick.blogspot.ca/ 할당량이 있기 때문에 여기에 코드를 붙여 넣지 않았습니다. 코드를이 코드와 비교해보십시오.이 코드는 테스트되고 작동합니다.

+0

나는 어떻게 그 순간을 기억하지만, 나는 내 광선 선택의 정확성에 관해서 내가 가진 문제를 바로 잡을 수 있었다. 내가 기억하는 것에서 나는 내가 어딘가에서 뺄셈을하고 있었거나, 그 반대의 경우를 빼고 모든 것을 던지고 있었다. 내 코드를 거칠게 보며 기회를 얻으면 다시 돌아올거야. –

+0

http://android-raypick.blogspot.ca/의 코드가 작동하는지 확인하고, 내 앱에서 사용하고 있습니다. 모든 계산은 정확하지만 메모리 할당은 엄청납니다. 광선의 교차를 900 개의 삼각형으로 검사하기 위해 킬로바이트의 메모리를 할당하지 않기 위해 코드를 재 설계 할 수 있습니다. – keaukraine

+0

@keaukraine : 나는 그것을 작동시키지 못하고, 여기에 질문을 올렸습니다. http://stackoverflow.com/questions/14185279/ray-picking-in-opengl-es-2-0, 여러분이보세요. 내가 바른 길을 가고 있는지 보아라. – Araw

관련 문제