2012-03-07 4 views
1

Iveはmin3dとオンラインで見つけたコードを使用して実装しましたが、私が実装したときに、ある時に間違ったものをクリックすると1つは選出されます。画面上でさえも選択されないものがあります。これは、最初の場所で実現し得るためにコードのかなりかかりましたが、私は呼ん主な二つの方法は次のとおりです。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; 
} 

は今、私はまた、錐台カリングが、それはので仕方ダウン物事を遅くすることを行ってた実装しようとしています私はそれを最適化するために多くのことをやっていません。しかし、いくつかの人が見て、おそらく素晴らしいだろうより正確にする方法について私にいくつかの指摘を与えることができます。私がピッキング方法と呼ぶHeres。あなたが衝突検出に間違いを作っているようにあなたが持っているバグが聞こえる

_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