1

openGL では、論文「Fast, Minimum Storage Ray/Triangle Intersection」( http://jgt.akpeters.com/papers/MollerTrumbore97 / )。

私のカーソル位置は、次のコードを使用してワールド空間に投影されていません:

bool SCamera::unproject(Vector3 input, Vector3 & output){

  GLint viewport[4]; 
  glGetIntegerv(GL_VIEWPORT,viewport); //Grab screen info

  float x = input.mX; 
  float y = input.mY;
  float z = input.mZ;

  Matrix4 P, Mv, res;

  P = getProjection();
  Mv = getCameraTransform();

  Vector3 N; //Cursor point translated to having 0,0 at screen center
  N.mX = ((x-viewport[0]) / viewport[2])*2 - 1;
  N.mY = ((y-viewport[1]) / viewport[3])*2 - 1;
  N.mZ = z*2-1;

  res = P * Mv; //Multiply P * Mv to get transform
  Vector3 w = res.inverse() * N; //Apply transform to N.

  output.mX = w[0];
  output.mY = w[1];
  output.mZ = w[2];
  return true;
}

その後、次のようにして光線を形成します。

unproject(Vector3(xClick, yClick,0),resultUnproject)
ray.origin = cameraPosition;
ray.direction = resultUnproject - ray.origin;
ray.direction.normalize();

さて、最後に、この光線を三角形のコード (上記のリンク) で実行しようとしていますが、正しく変換できないようです。私の現在の試みは次のとおりです。

Matrix4 mview, T;
mview = getModelview();
T = mview.inverse();
ray.origin = T*ray.origin;
ray.direction = T*ray.direction;
ray.direction.normalize();

何らかの理由で、これは機能しません。私は私の光線を間違って形成していますか?それとも間違って変換しますか?

4

4 に答える 4

3

これに対する私の解決策は、sje397 が提案したことを実行することでしたが、結果を新しい光線として使用するだけでした。

したがって、私のプロジェクト(XNA)ではray、カーソルから投影されていない場合:

rayTransform = Matrix.Invert(model_transform);

//Transform ray (or more accurately its defining components into a new ray)
Vector3 v1 = Vector3.Transform(ray.Position, rayTransform);
Vector3 v2 = Vector3.Transform((ray.Position + ray.Direction), rayTransform);
transformedray = new Ray(v1, v2 - v1);

model_transformここでは、シェーダーの変換と同じ方法で生成されます (つまり、ワールド/ローカル乗算などのスワップはありません)。

これは私のプロジェクトではうまく機能し、ピッキングのターゲットはあらゆる方法で回転、変換、スケーリングされます。

また、これは少し生意気に感じるかもしれませんが、それでも問題が解決しない場合は、カーソルをアンプロジェクションしてピッキング レイを生成するコードが正しく機能することを確認してください。トライアングル ピッキング コードが機能する場合は、そうしなければならないと思いますが、「ラウンド アバウト」の方法でレイを取得しているように見えます。

私のプロジェクトでは、ビューポートの「平面」上にある 2 つのポイントを取るので、Vector3(cursorx,cursory,0)これもまた Z 軸上を進みますVector3(cursorx,cursory,1)。これらの両方の点を非投影にします。最初の結果が原点で、差が方向です。

幸運を!

于 2011-02-12T18:27:13.020 に答える
3

1つの方法は次のとおりです。

光線の原点を取り、ワールド空間で光線の方向に単位距離でポイントを計算します。次に、両方のポイントに変換を行います。つまり、変換行列の逆数を掛けます。次に、平行移動した 2 つの点の差から新しい光線の方向を決定できます。この方向が元の方向と異なるかどうかを確認すると、ステップが抜けているかどうかがすぐにわかります。

于 2010-10-18T23:32:00.090 に答える
0

方法には満足していませんが、最終的にこれが機能するようになりました。私の場合、個々のモデルの回転はレンダリング前に変換として適用されるため、モデルビュー マトリックスによってターゲットの三角形を変換する必要がありました。

私が上でやろうとしていたのは、あたかもオブジェクトが回転したかのように、オブジェクトの周りで光線の原点を移動することによって、同じ目的を果たす光線を計算することでした。残念ながら、私は数学を正しく理解できませんでした。

最終結果は、レイごとに 1 つではなく、三角形ごとに 1 つの変換を意味します。幸いなことに、私はこれをピッキングにのみ使用しているため、パフォーマンスへの影響はそれほど大きくないようです。

于 2010-10-22T13:02:31.010 に答える
0

いくつかの光線 (すでにワールド空間に変換されている) があり、それがオブジェクト/三角形と交差するかどうかを確認したい場合は、オブジェクトの逆行列を乗算する必要があります。ここにいくつかの擬似コードがあります:

NewRayPosition = Vector3.Transform(OldRay.Position, Matrix.Invert(Transformation);
NewRayDirection = Vector3.Transform(OldRay.Direction, Matrix.Invert(Rotation*Scale));
NewRayDirection.Normalize();

光線の位置に Translation、Scale、および Rotation を乗算しますが、方向には Scale と Rotation のみを乗算します。あなたが行った方法でそれを行うことは、パフォーマンス上の理由から容認できません。詳細はこちら: http://www.cl.cam.ac.uk/teaching/1999/AGraphHCI/SMAG/node2.html#SECTION00024100000000000000

于 2013-06-14T15:19:52.000 に答える