2012-01-03 12 views
0

私は何らかの理由で完全に正しく動作しない3Dピッキングを行うためのコードを書いています! (イムは、あなたが知っているだけのようLWJGLを使用。)3Dピッキングlwjgl

このコードがどのように見えるかです:

if(Mouse.getEventButton() == 1) { 
    if (!Mouse.getEventButtonState()) { 
    Camera.get().generateViewMatrix(); 

    float screenSpaceX = ((Mouse.getX()/800f/2f)-1.0f)*Camera.get().getAspectRatio(); 
    float screenSpaceY = 1.0f-(2*((600-Mouse.getY())/600f)); 
    float displacementRate = (float)Math.tan(Camera.get().getFovy()/2); 

    screenSpaceX *= displacementRate; 
    screenSpaceY *= displacementRate; 

    Vector4f cameraSpaceNear = new Vector4f((float) (screenSpaceX * Camera.get().getNear()), (float) (screenSpaceY * Camera.get().getNear()), (float) (-Camera.get().getNear()), 1); 
    Vector4f cameraSpaceFar = new Vector4f((float) (screenSpaceX * Camera.get().getFar()), (float) (screenSpaceY * Camera.get().getFar()), (float) (-Camera.get().getFar()), 1); 

    Matrix4f tmpView = new Matrix4f(); 
    Camera.get().getViewMatrix().transpose(tmpView); 
    Matrix4f invertedViewMatrix = (Matrix4f)tmpView.invert(); 

    Vector4f worldSpaceNear = new Vector4f(); 
    Matrix4f.transform(invertedViewMatrix, cameraSpaceNear, worldSpaceNear); 

    Vector4f worldSpaceFar = new Vector4f(); 
    Matrix4f.transform(invertedViewMatrix, cameraSpaceFar, worldSpaceFar); 


    Vector3f rayPosition = new Vector3f(worldSpaceNear.x, worldSpaceNear.y, worldSpaceNear.z); 
    Vector3f rayDirection = new Vector3f(worldSpaceFar.x - worldSpaceNear.x, worldSpaceFar.y - worldSpaceNear.y, worldSpaceFar.z - worldSpaceNear.z); 

    rayDirection.normalise(); 

    Ray clickRay = new Ray(rayPosition, rayDirection); 

    Vector tMin = new Vector(), tMax = new Vector(), tempPoint; 
    float largestEnteringValue, smallestExitingValue, temp, closestEnteringValue = Camera.get().getFar()+0.1f; 
    Drawable closestDrawableHit = null; 
    for(Drawable d : this.worldModel.getDrawableThings()) { 
     // Calcualte AABB for each object... needs to be moved later... 
     firstVertex = true; 
     for(Surface surface : d.getSurfaces()) { 
      for(Vertex v : surface.getVertices()) { 
       worldPosition.x = (v.x+d.getPosition().x)*d.getScale().x; 
       worldPosition.y = (v.y+d.getPosition().y)*d.getScale().y; 
       worldPosition.z = (v.z+d.getPosition().z)*d.getScale().z; 
       worldPosition = worldPosition.rotate(d.getRotation()); 
       if (firstVertex) { 
        maxX = worldPosition.x; maxY = worldPosition.y; maxZ = worldPosition.z; 
        minX = worldPosition.x; minY = worldPosition.y; minZ = worldPosition.z; 
        firstVertex = false; 
       } else { 
        if (worldPosition.x > maxX) { 
         maxX = worldPosition.x; 
        } 
        if (worldPosition.x < minX) { 
         minX = worldPosition.x; 
        } 
        if (worldPosition.y > maxY) { 
         maxY = worldPosition.y; 
        } 
        if (worldPosition.y < minY) { 
         minY = worldPosition.y; 
        } 
        if (worldPosition.z > maxZ) { 
         maxZ = worldPosition.z; 
        } 
        if (worldPosition.z < minZ) { 
         minZ = worldPosition.z; 
        } 
       } 
      } 
     } 

     // ray/slabs intersection test... 


     // clickRay.getOrigin().x + clickRay.getDirection().x * f = minX 
     // clickRay.getOrigin().x - minX = -clickRay.getDirection().x * f 
     // clickRay.getOrigin().x/-clickRay.getDirection().x - minX/-clickRay.getDirection().x = f 
     // -clickRay.getOrigin().x/clickRay.getDirection().x + minX/clickRay.getDirection().x = f 


     largestEnteringValue = -clickRay.getOrigin().x/clickRay.getDirection().x + minX/clickRay.getDirection().x; 
     temp = -clickRay.getOrigin().y/clickRay.getDirection().y + minY/clickRay.getDirection().y; 
     if(largestEnteringValue < temp) { 
      largestEnteringValue = temp; 
     } 
     temp = -clickRay.getOrigin().z/clickRay.getDirection().z + minZ/clickRay.getDirection().z; 
     if(largestEnteringValue < temp) { 
      largestEnteringValue = temp; 
     } 

     smallestExitingValue = -clickRay.getOrigin().x/clickRay.getDirection().x + maxX/clickRay.getDirection().x; 
     temp = -clickRay.getOrigin().y/clickRay.getDirection().y + maxY/clickRay.getDirection().y; 
     if(smallestExitingValue > temp) { 
      smallestExitingValue = temp; 
     } 
     temp = -clickRay.getOrigin().z/clickRay.getDirection().z + maxZ/clickRay.getDirection().z; 
     if(smallestExitingValue < temp) { 
      smallestExitingValue = temp; 
     } 


      if(largestEnteringValue > smallestExitingValue) { 
       //System.out.println("Miss!"); 
      } else { 
       if (largestEnteringValue < closestEnteringValue) { 
        closestEnteringValue = largestEnteringValue; 
        closestDrawableHit = d; 
       } 
      } 

    } 
    if(closestDrawableHit != null) { 
     System.out.println("Hit at: (" + clickRay.setDistance(closestEnteringValue).x + ", " + clickRay.getCurrentPosition().y + ", " + clickRay.getCurrentPosition().z); 
     this.worldModel.removeDrawableThing(closestDrawableHit);  
    } 
    } 
} 

私はちょうど間違っているのか理解していない、光線が撮影していると私は削除されるヒットものを行いますその光線の結果は時々クリックしているものを取り除き、時にはそれをクリックしているものに近くないものを取り除き、時には何も取り除かないことがあります。

編集:

わかりましたので、私は私が今送信イム線とoviously何か問題があることは、SEができます(それはtravles SmaIでドットをペイントすることにより)エラーと光線をデバッグすることにより、検索を続けてきました私のカメラを指示しているにもかかわらず、それは世界の中心近くにその起源を持ち、常に同じ位置にショットする...

私の最初のtoughtsは私のviewMatrixを計算する方法にいくつかのエラーがあるかもしれない(lwjglのglulookatメソッドからviewmatrixを取得することは不可能であるため、私は自分自身を構築しなければならず、問題がどこにあるかを推測しています)...

EDIT2:

これは私は現在、それを計算する方法である:これは間違っているか、右のであれば、それは間違っているならば、誰でも確認することができれば

private double[][] viewMatrixDouble = {{0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,0,0,1}}; 

public Vector getCameraDirectionVector() { 
    Vector actualEye = this.getActualEyePosition(); 
    return new Vector(lookAt.x-actualEye.x, lookAt.y-actualEye.y, lookAt.z-actualEye.z); 
} 

public Vector getActualEyePosition() { 
    return eye.rotate(this.getRotation()); 
} 

public void generateViewMatrix() { 

    Vector cameraDirectionVector = getCameraDirectionVector().normalize(); 
    Vector side = Vector.cross(cameraDirectionVector, this.upVector).normalize(); 
    Vector up = Vector.cross(side, cameraDirectionVector); 

    viewMatrixDouble[0][0] = side.x;     viewMatrixDouble[0][1] = up.x;     viewMatrixDouble[0][2] = -cameraDirectionVector.x;     
    viewMatrixDouble[1][0] = side.y;     viewMatrixDouble[1][1] = up.y;     viewMatrixDouble[1][2] = -cameraDirectionVector.y;     
    viewMatrixDouble[2][0] = side.z;     viewMatrixDouble[2][1] = up.z;     viewMatrixDouble[2][2] = -cameraDirectionVector.z;     


    /* 
    Vector actualEyePosition = this.getActualEyePosition(); 
    Vector zaxis = new Vector(this.lookAt.x - actualEyePosition.x, this.lookAt.y - actualEyePosition.y, this.lookAt.z - actualEyePosition.z).normalize(); 
    Vector xaxis = Vector.cross(upVector, zaxis).normalize(); 
    Vector yaxis = Vector.cross(zaxis, xaxis); 
    viewMatrixDouble[0][0] = xaxis.x;     viewMatrixDouble[0][1] = yaxis.x;     viewMatrixDouble[0][2] = zaxis.x;     
    viewMatrixDouble[1][0] = xaxis.y;     viewMatrixDouble[1][1] = yaxis.y;     viewMatrixDouble[1][2] = zaxis.y;     
    viewMatrixDouble[2][0] = xaxis.z;     viewMatrixDouble[2][1] = yaxis.z;     viewMatrixDouble[2][2] = zaxis.z;     
    viewMatrixDouble[3][0] = -Vector.dot(xaxis, actualEyePosition); viewMatrixDouble[3][1] =-Vector.dot(yaxis, actualEyePosition); viewMatrixDouble[3][2] = -Vector.dot(zaxis, actualEyePosition); 
    */ 
    viewMatrix = new Matrix4f(); 
    viewMatrix.load(getViewMatrixAsFloatBuffer()); 
} 

はverry greatfullだろう。私はこのことについて、スレッドとドキュメンテーションをたくさん読みましたが、私はそれのまわりで私の頭を包む縫い目ができない ...それを行うための正しい方法で私を供給する...

答えて

0

私は最終的にgamedevと友人の助けを借りて解決しました。ここにはanswerのコードが掲載されています。

0

私は理解していません何が間違っている、レイが撮影されていると私は削除されるものをヒットしますが、物事は私が画面上で押すと消えていません。

OpenGLはシーングラフではなく、描画ライブラリです。したがって、内部表現から何かを削除した後、シーンを再描画する必要があります。そしてあなたのコードでは、再描画をトリガする関数への呼び出しがありません。

+0

返信いただきありがとうございます。申し訳ありませんが、私は少し不明ですが、それは私のプログラム全体ではなく、3Dピッキング(世界のコントローラにある)を処理する部分だけです。シーンのレンダリングは、プログラムの別の部分で実行されます(ワールドビュー)。 削除されたオブジェクトの結果は表示できますが、何らかの理由で間違ったオブジェクトが削除されてしまいます。 – Wirde

関連する問題