簡體   English   中英

C#和XNA使對象圍繞另一個對象旋轉,以保持偏移量(或如何將隨機點換膚)

[英]C# and XNA rotate an object around another object keeping the offset (or HOW TO SKIN A RANDOM POINT AGAINS A RANDOM BONE)

我有一個以四元數表示的對象X,位於世界空間中,我們稱之為后者X_Base。 我有另一個對象Y,它與對象X偏移,並由稱為“ Y_Base”的四元數矩陣表示。

那就是他們在零時的頭寸,在第一時他們改變頭寸。 對象Y繞其軸旋轉一定角度,我知道它是新的四元數,它是Y_New。 X相對於Y旋轉,以使偏移量保持在時間0。我需要的基本上是X_New。

用英語,我正在嘗試手動為模型蒙皮。 我有一個與骨骼偏移一定距離的網格,我需要它在骨骼旋轉時保持此偏移。 為什么我找不到我需要使用的公式的明確答案。

對於任何建議將不勝感激。

進一步說明:

想象一個太陽系,地球繞太陽繞太陽軸旋轉。 我們這樣說,即月亮不會繞地球旋轉,而是與地球偏移,無論您如何改變地球的位置,月亮都保持偏移。 我需要的是找出月亮在時間1的位置,同時知道月亮在時間0的位置以及地球在時間0和時間1的位置。

我能夠為模型蒙皮。 這是我所做的:

  1. “太陽”是我模特的骨頭。 它可以平移(在世界空間中)並旋轉。 “地球”是模型上的一個自定義點,可以隨模型一起旋轉/平移,因為我的目標意味着我不能隨便拾取任何點並對其進行蒙皮,我需要后者隨模型一起移動。

  2. 我的應用程序中有兩種方法:一種方法啟動一次(初始化),另一種方法啟動每幀(更新)。 在Initialize方法中,我的模型始終處於T姿勢。

  3. 在初始化方法中,我將太陽和地球的位置讀取為2 XNA Matrix

  4. 在初始化中,我還計算

     Vector3 Difference = TPoseEarth.Translation - TPoseSun.Translation; 
  5. 最后,在“初始化”中,我分解了Sun的Matrix以獲得純Sun的旋轉矩陣(不帶平移)。 之所以這樣做,是因為即使在T姿勢下,我模型的骨骼Sun顯然也分配有一個非同一性矩陣。 像這樣:

     Vector3 scale; Quaternion rotation; Vector3 tra; TPoseSun.Decompose(out scale, out rotation, out tra); BaseSunRot = Matrix.CreateFromQuaternion(rotation); 
  6. 在更新方法中,我獲得地球和太陽的當前世界位置。 我分解太陽矩陣以獲得純旋轉(再次!)。

     Vector3 scale; Quaternion rotation; Vector3 tra; Sun.Decompose(out scale, out rotation, out tra); Matrix SunRot = Matrix.CreateFromQuaternion(rotation); 
  7. 我通過將基本旋轉的倒數乘以新的旋轉來計算唯一的骨骼太陽旋轉:

     Matrix UniqueRot = Matrix.Invert(BaseSunRot) * SunRot; 
  8. 我將地球的平移設置為等於差異(在太陽的T姿勢位置與地球的T姿勢位置之間):

     Matrix Earth = Matrix.Identity; Earth.Translation = Difference; 
  9. 我將地球矩陣乘以唯一骨骼(太陽)的旋轉:

     Earth *= UniqueRot; 
  10. 我添加了Sun的CURRENT位置,以提供幀之間的可能轉換:

     Earth += Sun.Translation; 
  11. 結束。 地球矩陣包含有關蒙皮頂點的所有必要信息。

我不確定100%,但是我覺得這基本上是一本手冊,介紹如何對任意給定的點再次蒙皮世界上的任何骨骼(即旋轉/平移以保持初始偏移)。 問題是,代碼未優化:)。 如果有人對如何優化它有任何想法,我將不勝感激。

特別是我想知道是否可以跳過雙矩陣分解並僅將整個ScaleRotationTranslation矩陣相乘? 我正在嘗試,但沒有成功。

您可能會因為“四元數”而迷失了我,但是我已經看到了許多有關此問題的2D示例,並且總有一種簡單的解決方法:

基本上,您需要為兩個對象使用完全相同的originrotation ,以便它們將自動在它們之間保持恆定的偏移量。

對於初學者來說,如果您使用矩陣而不是四元數,那么您會發現這個問題更加直接。 四元數僅包含旋轉,因此您需要將平移(位置)分別存儲在向量中,而矩陣同時包含旋轉和平移。

對於太陽系,您將為太陽和地球分配一個世界矩陣。 太陽的位置應使其中心位於世界原點[0,0,0]。 太陽的矩陣將包含其繞y軸的旋轉(使其旋轉)。

sun.World = Matrix.CreateRotationY(angle);

地球將相對於太陽有一個位置。 該值將保持不變,並用於創建轉換矩陣。 然后,如果將此矩陣與太陽的世界矩陣相乘,您將得到地球的世界矩陣:

earth.World =
    Matrix.CreateTranslation(earth.Position) *
    sun.World;

注意矩陣乘法的順序很重要。 隨着時間的推移,這將繞着太陽旋轉地球的位置。 旋轉也可以應用於地球,使其繞其軸旋轉,如下所示:

earth.World =
    Matrix.CreateRotationY(angle) *
    Matrix.CreateTranslation(earth.Position) *
    sun.World;

要將月球定位在圍繞地球的軌道上,可以應用相同的本壘:

moon.World =
    Matrix.CreateTranslation(moon.Position) *
    earth.World;

如果需要使用四元數,可以將它們與矩陣進行相互轉換:

Quaternion quaternion = Quaternion.CreateFromRotationMatrix(matrix);
Vector3 translation = matrix.Translation;

Matrix matrix = Matrix.CreateFromQuaternion(quaternion);
matrix = Matrix.CreateTranslation(translation) * matrix;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM