2012-02-07 8 views
3

概要「をご覧」:マトリックス変換は、カメラを再作成する機能

私は、3D空間での一連の点を与えています、と私は任意の視角からそれらを分析します。私は、WPFでOpenGLの "Look At"機能を再現する方法を理解しようとしています。私はマウスを動かして、XとYがそれぞれカメラのPhiとTheta球面座標を操作するようにして、私がマウスを動かすと、カメラは点群の中心(一般的には起点)を回るように見えます、私がやった何

を見てのターゲットを表すであろう:

を、私は、次のコードを作ってきた、これまでのところ、私が欲しいものをやっていません。

internal static Matrix3D CalculateLookAt(Vector3D eye, Vector3D at = new Vector3D(), Vector3D up = new Vector3D()) 
    { 
     if (Math.Abs(up.Length - 0.0) < double.Epsilon) up = new Vector3D(0, 1, 0); 
     var zaxis = (at - eye); 
     zaxis.Normalize(); 
     var xaxis = Vector3D.CrossProduct(up, zaxis); 
     xaxis.Normalize(); 
     var yaxis = Vector3D.CrossProduct(zaxis, xaxis); 

     return new Matrix3D(
      xaxis.X, yaxis.X, zaxis.X, 0, 
      xaxis.Y, yaxis.Y, zaxis.Y, 0, 
      xaxis.Z, yaxis.Z, zaxis.Z, 0, 
      Vector3D.DotProduct(xaxis, -eye), Vector3D.DotProduct(yaxis, -eye), Vector3D.DotProduct(zaxis, -eye), 1 
      ); 
    } 

私はこのリンクからアルゴリズムを得ました:http://msdn.microsoft.com/en-us/library/bb205342(VS.85).aspx

私は、この使用してすべての点に戻ったマトリックスを適用します。私はatベクトルとして全ての点の中心を計算しています、と私は(center.X,center.Y,center.Z + 100)で私の最初のeyeベクトルを設定してきた

var vector = new Vector3D(p.X, p.Y, p.Z); 

    var projection = Vector3D.Multiply(vector, _camera); // _camera is the LookAt Matrix 

    if (double.IsNaN(projection.X)) projection.X = 0; 
    if (double.IsNaN(projection.Y)) projection.Y = 0; 
    if (double.IsNaN(projection.Z)) projection.Z = 0; 

    return new Point(
     (dispCanvas.ActualWidth * projection.X/320), 
     (dispCanvas.ActualHeight * projection.Y/240) 
     ); 

を遠く離れた私は、球座標を取得し、CalculateLookAt関数にそれを置くために、マウスの動きを取ると、次のコードを適用するすべてのポイント

からたくさんいるです:

 var center = GetCenter(_points); 
     var pos = e.GetPosition(Canvas4); //e is of type MouseButtonEventArgs 
     var delta = _previousPoint - pos; 

     double r = 100; 
     double theta = delta.Y * Math.PI/180; 
     double phi = delta.X * Math.PI/180; 

     var x = r * Math.Sin(theta) * Math.Cos(phi); 
     var y = r * Math.Cos(theta); 
     var z = -r * Math.Sin(theta) * Math.Sin(phi); 

     _camera = MathHelper.CalculateLookAt(new Vector3D(center.X * x, center.Y * y, center.Z * z), new Vector3D(center.X, center.Y, center.Z)); 

     UpdateCanvas(); // Redraws the points on the canvas using the new _camera values 

結論:

これは、ポイントの周りにカメラの軌道を作成しません。 Look At関数の使い方を理解していないか、数式が間違っています。

ご協力いただければ幸いです。

+0

マウスをまだ使用していないので、 'theta'と' phi'の値を試してみてください。 (0、0)は機能しますか?どのように(0、0.1)ですか? (0.1、0)?... – Beta

答えて

4

Vector3Dは、アフィン空間で変換されません。 Vector3Dは、アフィン空間には存在しないベクトルであるため、翻訳されません。変換コンポーネントを含む3Dベクトル空間)、ベクトル空間でのみ使用できます。あなたはPoint3Dを必要とする:あなたのベクトルが[1,1,1]あるので、それは、各コンポーネントの10 + 1あるべきな

var m = new Matrix3D(
       1, 0, 0, 0, 
       0, 1, 0, 0, 
       0, 0, 1, 0, 
       10, 10, 10, 1); 

var v = new Point3D(1, 1, 1); 
var r = Point3D.Multiply(v, m); // 11,11,11 

は、あなたの推定の答えも間違っています。

+0

ああ!ありがとう、それは私が探していたものです:)私はPoint3Dも見ていませんでした。はい、私は全てのポイントをポイントではなくベクトルとして扱っていました。お役立ち情報 –

-2

Matrix3Dライブラリにはいくつか興味深い問題があります。

Vector3D.Multiply(vector, matrix)はベクターを翻訳しないことに気付きました。例えば

var matrixTest = new Matrix3D(
    1, 0, 0, 0, 
    0, 1, 0, 0, 
    0, 0, 1, 0, 
    10, 10, 10, 1 
    ); 

var vectorTest = new Vector3D(1, 1, 1); 

var result = Vector3D.Multiply(vectorTest, matrixTest); 
// result = {1,1,1}, should be {11,11,11} 

私は、コードが機能するためには、基本的な行列の数学関数の一部を書き換えることになりました。

ロジック面を除いてすべてが機能していましたが、それは問題だったMatrix3Dライブラリによって処理された基本的な数学でした。

ここに修正があります。すべてのVector3D.Multiplyメソッド呼び出しを次のように置き換えます。

public static Vector3D Vector3DMultiply(Vector3D vector, Matrix3D matrix) 
    { 
     return new Vector3D(
      vector.X * matrix.M11 + vector.Y * matrix.M12 + vector.Z * matrix.M13 + matrix.OffsetX, 
      vector.X * matrix.M21 + vector.Y * matrix.M22 + vector.Z * matrix.M23 + matrix.OffsetY, 
      vector.X * matrix.M31 + vector.Y * matrix.M32 + vector.Z * matrix.M33 + matrix.OffsetZ 
      ); 
    } 

すべてが機能します。

+1

これはうまくいきますが、Vector3Dの代わりにPoint3Dを使用する方がずっと良い方法です。 –

関連する問題