2011-08-04 6 views
2

2つの3Dオブジェクト間の距離を測定する方法を理解したいと思います。それらを親オブジェクトと子オブジェクトと呼ぶことにしましょう。親は車のボディ、子供は車の車輪と考えてください。XNAを使用している親オブジェクトの向きに関連した、Matrixオブジェクト間の距離?

ワールド空間のオブジェクトの位置に基づいて違いを得る方法を理解していますが、親オブジェクトの相対的なオブジェクト空間に基づく測定として違いを得たいと思います。

例:親が東向きで、子が2X、親から3Yの場合、相対的な意味で測定されます。親が60度回転した場合、子供の相対的な位置は、オブジェクト空間内の2x、3yの距離にとどまる。世界の空間の感覚のように、Vector3としての子オブジェクトの測定値はかなり異なっています。

基本的には、特許の右側にある子オブジェクトが常に親オブジェクトの右にとどまるように、違いを得るための予測可能な方法が必要です。

これは、親コンポーネントであるが、このアップデートは、すべてのフレームを実行している:

[Serializable] 
    public class Component_Parent : BaseComponentAutoSerialization<ISceneEntity> 
    { 
     public override void OnUpdate(GameTime gameTime) 
     { 
      PassThrough.ParentMatrix = ParentObject.World; 
      PassThrough.ParentTranslation = ParentObject.World.Translation; 


     } 
    } 

この次の部分は、子コンポーネントである:

[Serializable] 
    public class Component_Child : BaseComponentAutoSerialization<ISceneEntity> 
    { 
     Vector3 _parentOffset; 
     Quaternion _parentQuaternionOffset; 

     public override void OnUpdate(GameTime gameTime) 
     { 
      // Get a sceneobject from the ParentObject 
      SceneObject sceneobject = (SceneObject)ParentObject; 

      // This relies on the position never being at 0,0,0 for setup, so please don't do that 
      // or change it with more look ups so that you don't need to rely on a Zero Vector3 :-) 
      if (PassThrough.GroupSetupMode || _parentOffset == Vector3.Zero) 
      { 
       if (PassThrough.ParentTranslation != Vector3.Zero) 
       { 
        _parentOffset = sceneobject.World.Translation - PassThrough.ParentTranslation; 

        // Decompose World Matrix (Parent) 
        Quaternion parentQ = new Quaternion(); 
        Vector3 parentSpot = new Vector3(); 
        Vector3 parentScale = new Vector3(); 
        PassThrough.ParentMatrix.Decompose(out parentScale, out parentQ, out parentSpot); 

        Matrix identity = Matrix.Identity; 

        // Decompose Identity Matrix (Parent) 
        Quaternion identityQ = new Quaternion(); 
        Vector3 identitySpot = new Vector3(); 
        Vector3 identityScale = new Vector3(); 
        identity.Decompose(out identityScale, out identityQ, out identitySpot); 

        _parentQuaternionOffset = identityQ - parentQ; 
       } 
      } 
      else 
      { 
       if (_parentOffset != Vector3.Zero) 
       { 

        // Decompose World Matrix (Child) 
        Quaternion rotationQ = new Quaternion(); 
        Vector3 spot = new Vector3(); 
        Vector3 scale = new Vector3(); 
        sceneobject.World.Decompose(out scale, out rotationQ, out spot); 


        // Decompose World Matrix (Parent) 
        Quaternion parentQ = new Quaternion(); 
        Vector3 parentSpot = new Vector3(); 
        Vector3 parentScale = new Vector3(); 
        PassThrough.ParentMatrix.Decompose(out parentScale, out parentQ, out parentSpot); 

        Matrix location = Matrix.CreateTranslation(PassThrough.ParentTranslation); 
        Matrix rotation = Matrix.CreateFromQuaternion(parentQ); 

        Matrix rotation2 = Matrix.CreateFromQuaternion(_parentQuaternionOffset); 

        Matrix newWorld = rotation * location; 

        Vector3 testTranslation = newWorld.Translation + ((newWorld.Left * _parentOffset.X) + (newWorld.Up * _parentOffset.Y) + (newWorld.Forward * _parentOffset.Z)); 
        Matrix scaleM = Matrix.CreateScale(scale); 



        //sceneobject.World = scaleM * (rotation * (Matrix.CreateTranslation(testTranslation))); 
        sceneobject.World = (Matrix.CreateTranslation(testTranslation)); 
       } 
      } 
     } 
    } 

私はそれがを追跡することとは何かを持っていると思います恒等行列からのオフセット回転と、私はその効果のためにいくつかのコードを追加しようとし始めましたが、実際に次に何があるのか​​は分かりません。

追加:

私はワールド空間の方向を向いて親オブジェクトを持っている場合は、すべての作品は、問題だし、別の方向を向いていますし、子供は彼らが同じ量だけ回転させるように思われる場合には一緒にグループ化される。

私が試してみて、説明するデモビデオをアップロードしました:

http://www.youtube.com/watch?v=BzAKW4WBWYs

私は、コンポーネントの完全なコードを通じて、静的なパスとシーンエンティティを貼り付けました。

http://pastebin.com/5hEmiVx9

おかげ

+1

私はあなたの質問を理解していません。あなたは親/子の間の距離をしたいですか?または原点からの子供の距離? – namar0x0309

+0

親と子の間の、親の方向に対する相対的な距離。 –

+0

どのような方向であっても、子供は同じ距離になります。親の行列が適用され、次に子行列が適用されます。子の行列の平行移動部分が触られていない限り、距離は同じままです。 – namar0x0309

答えて

0

問題は、私がワールドスペースのオフセットを使用しようとしていた方法でした。 EFnetの上#XNAから点滅に おかげで、このコードは完璧に動作します:

[Serializable] 
    public class Component_Child_fromxna : BaseComponentAutoSerialization<ISceneEntity> 
    { 
     Vector3 _parentOffset; 
     Matrix _ParentMatrixOffset; 


     public override void OnUpdate(GameTime gameTime) 
     { 
      // Get a sceneobject from the ParentObject 
      SceneObject sceneObject = (SceneObject)ParentObject; 


      // This relies on the position never being at 0,0,0 for setup, so please don't do that 
      // or change it with more look ups so that you don't need to rely on a Zero Vector3 :-) 
      if (PassThrough.GroupSetupMode || _parentOffset == Vector3.Zero) 
      { 
       if (PassThrough.ParentTranslation != Vector3.Zero) 
       { 
        // The old offset - This is just in world space though... 
        _parentOffset = sceneObject.World.Translation - PassThrough.ParentTranslation; 

        // Get the distance between the child and the parent which we keep as the offset 
        // Inversing the ParentMatrix and multiplying it by the childs matrix gives an offset 
        // The offset is stored as a relative xyz, based on the parents object space 
        _ParentMatrixOffset = sceneObject.World * Matrix.Invert(PassThrough.ParentMatrix); 
       } 
      } 
      else 
      { 
       if (_parentOffset != Vector3.Zero) 
       { 

        //Matrix pLocation = Matrix.CreateTranslation(_parentOffset); 
        //sceneObject.World = Matrix.Multiply(pLocation, PassThrough.ParentMatrix); 

        sceneObject.World = Matrix.Multiply(_ParentMatrixOffset, PassThrough.ParentMatrix); 
       } 
      } 
     } 
    } 
0

は、2つのオブジェクト間の距離は、いずれかの方向の関数ではありません。

あなたが基本的に望むのは、子オブジェクトと親オブジェクトの向き線との距離です。グローバルデカルト座標系を持つと仮定すると、これはh = sqrt(x^2 + y^2)* sin(Theta)として簡単に計算できます.xとyは親に対する子の相対座標です。 x軸から測定した親の向き。

しかし、まだ質問が私に少し混乱しています。子供が親の右側にいることを確認したいのであれば、単に相対xをチェックしてみてください。それが正の場合は右にあり、負の場合には左にありますか?

+0

車の車輪を考える。私は右の車輪が車のボディに対して常に同じ場所にあるようにしたい。 –

+0

今はあなたが持っているものと正確には何が欠けているかの問題です。親の位置をxp、yp、子のxc、yc、距離d、親のThetaの向きとすると、xc = xp + d * cos(Theta)、yc = yp + d * sin(Theta)。 dは定数であり、xp、ypおよびThetaを変更することによって、親に対して一定の距離dを有する子の位置を見つけることができる。 – Ardavan

2

車の車輪を考える。私は右の車輪が車のボディに対して常に同じ スポットにあるようにします。

車の向きや位置によって車輪の位置がわかるように思えます。 XNAがここで手助けしなければならない方法の1つは、Model.CopyAbsoluteBoneTransformsTo(Matrix [])です。しかし、親子関係を手動で処理したいと思うようなコードになります。そこで、組み込みメソッドを使用せずにこれを行う方法があります。ロード時にオフセット情報があると仮定します。

車のロードを開始する前に(例えばLoadContentメソッドで)、&車のロード後、適切な位置にロードされたと仮定してオフセットを作成しますベクトル(_parentOffset)

Vector3 _parentOffset = wheel.meshes[?].ParentBone.Transform.Translation - car.meshes[?].ParentBone.Transform.Translation;//where ? is the mesh index of the mesh you are setting up. 

そのベクターを保存し、それを変更しないでください。車の行列がずれて回転し、または位置された後

その後、このような車の行列を設定します。

Matrix wheelMatrix = carMatrix; 
wheelMatrix.Translation += (wheelMatrix.Right * _parentOffset.X) + 
          (wheelMatrix.Up * _parentOffset.Y) + 
          (wheelMatrix.Backward * _parentOffset.Z); 

これは、ホイール行列が車から任意の回転と並進の情報を継承しますがすることができます車の向き/位置に関係なく車輪の位置を適切に移動させる。

+0

これは次のようになっていますか? 行列wheelMatrix = PassThrough.ParentMatrix; wheelMatrix.Translation + =(wheelMatrix.Backward * _parentOffset.X)+(wheelMatrix.Up * _parentOffset.Y) +(wheelMatrix.Right * _parentOffset.Z); 余分な角括弧を使用する意味ですか? –

+0

また、なぜ私が持っていたもの(newWorld.Left * _parentOffset.X)ではなく、(wheelMatrix.Backward * _parentOffset.X)でしょうか? –

+0

はい、申し訳ありませんが、(WheelMatrix.Right * _parentOffset.X)+(wheelMatrix.Up * _parentOffset.Y)+(wheelMatrix.Backward * _parentOffset.Z) ;私は間違って書いたのか分からなかった。私はそれを編集します。それがあなたのためにそれをクリアするかどうか私に教えてください。 –

関連する問題