2014-10-18 156 views
0

我有三個對象:marshal,sergeant,soldier。他們都是Human類型:繼另一個旋轉的對象

class Human{ 
public: //just to make question less complicated, 
//let's assume all members are public 
    DirectX::XMFLOAT3 position; //pivot point 
    DirectX::XMFLOAT3 rotation; 

    Human * follow; 
    std::vector<Human *> followers; 
    DirectX::XMFLOAT3 distanceToFollow; 

    ... 
    void render(){ 
     ... 
     DirectX::XMMATRIX objectWorldMatrix = DirectX::XMMatrixIdentity(); 
     DirectX::XMMATRIX rotationMatrix = 
     DirectX::XMMatrixRotationX(rotation.x) * 
     DirectX::XMMatrixRotationY(rotation.y) * 
     DirectX::XMMatrixRotationZ(rotation.z) 
    ); 
     ... 
     DirectX::XMMATRIX translationMatrix = DirectX::XMMatrixTranslation(position.x, position.y, position.z); 
     objectWorldMatrix = scaleMatrix * rotationMatrix * translationMatrix; 
     ... 
    } 

    void follow(Human * h){ 
     follow = h; 
     h.followers.push_back(this); 
     distanceToFollow = h.position - position; 
    } 
}; 

它們之間的關係看起來像這樣:

soldier.follow(sergeant); 
sergeant.follow(marshal); 

我現在想的是做soldier以下sergeantsergeantmarshal。所以,當,例如,marshal動作,大家移動,並保持它們的距離(以及相對角度)彼此(以下簡稱「可視化」是2D的簡化,但我與3D模型的工作):

enter image description here

對於位置的變化,會做:

void Human::setPosition(XMFFLOAT3 newPosition){ 
    position = newPosition; 
    for(auto &follower : followers){ 
     follower.setPosition(newPosition - follower.distanceToFollow); 
     //keep the distance, soldier! 
    } 
} 

但我想不通,如何使旋轉相同?

marshal旋轉時,sergeant將改變其positionrotation

我幾次失敗後。在我最後一次嘗試,當我通過[40, 0, 0],然後[0, 30, 0],然後[-40, 0, 0][0, -30, 0]旋轉marshalsergeant到位不同的結束,那麼所有這些旋轉(marshal支持的地方,因爲它應該與旋轉[0, 0, 0] - 的相對距離已被打破)前。也許這是因爲計算的順序。

不管怎樣,我不想提出解決問題的方法不對,所以將只問你:如何編寫Human::setRotation(XMFFLOAT3 newRotation)方法?

注意:現在沒有插值/動畫(從一個狀態到另一個狀態),所以我猜四元數不是必須的。


我嘗試

起初我不想將它張貼。這是因爲我認爲它包含了一些錯誤,我不想向你推薦它們(我認爲比較正確的解決方案比找到錯誤的錯誤更容易)。但是,如果你想檢查我的缺陷代碼:

Human::setRotation(XMFFLOAT3 newRotation){ 
    XMFFLOAT3 oldRotation = rotation; 
    rotation = newRotation; 
    for(auto &follower : followers){ 
     follower.rotateAround(newRotation - oldRotation, rotationDiffrenceToFollowTarget, position); 
     //keep the relative angle, soldier! 
    } 
} 

Human::rotateAround(XMFFLOAT3 radians, XMFFLOAT3 origin){ 
    DirectX::XMMATRIX rotX = DirectX::XMMatrixRotationX(radians.x); 
    DirectX::XMMATRIX rotY = DirectX::XMMatrixRotationY(radians.y); 
    DirectX::XMMATRIX rotZ = DirectX::XMMatrixRotationZ(radians.z); 

    DirectX::XMMATRIX worldM = rotX * rotY * rotZ; 

    DirectX::XMFLOAT3 positionTemp = DirectX::XMFLOAT3(
     position.x - origin.x, position.y - origin.y, position.z - origin.z); 
    DirectX::XMVECTOR pos = XMLoadFloat3(&positionTemp); 
    pos = XMVector3Transform(pos, worldM); 
    XMStoreFloat3(&positionTemp, pos); 

    positionTemp.x = positionTemp.x + origin.x; 
    positionTemp.y = positionTemp.y + origin.y; 
    positionTemp.z = positionTemp.z + origin.z; 

    setPosition(positionTemp); //so followers will get noticed 
    rotation += radians; 
} 

而且rotationDiffrenceToFollowTarget計算如下:

Human::void follow(Human * h){ 
    follow = h; 
    h.followers.push_back(this); 
    distanceToFollow = h.position - position; 
    rotationDiffrenceToFollowTarget = h.rotation - rotation; 
} 

回答

1

你不能減去一組三個旋轉角和期待感,因爲3D旋轉別通勤,這幾乎毀了你的方法。您的三個角度區域對於任何事物都沒有多大用處 - 它是您想要存儲的一體化矩陣。

做到這一點的方法是表達領袖的每一個人移動作爲一個單一的矩陣和矩陣正好適用於跟隨者。對於翻譯來說,這個矩陣只是一個翻譯,對於旋轉來說,它是領導翻譯成原點,然後是簡單的旋轉,反映引起它的UI操作,然後是反向翻譯。當我說「其次」時,我的意思是「預乘」。

如果該UI動作應該是以字符爲中心的,即如果向左轉動時感覺與上一次相同,那麼在應用更改之前還必須展開當前的旋轉,然後重新應用它,但翻譯仍然是最外面的。如果沒有這個跟隨領導者的特徵,那麼這個特徵就會簡化爲將當前矩陣後乘以變化,但對於追隨者,您將應用領導者當前矩陣的逆矩陣,然後應用變化,然後應用舊的當前矩陣。

這不會與以後的事你多階段的工作,所以你必須要表達直接跟隨一個領導者都跟隨。

另一種選擇是找到轉變領導者的整個狀態上的跟隨者,當你周圍的領導者移動通過矩陣postmultiply他的狀態得到追隨者的狀態矩陣。所謂「狀態」是指表示爲單個矩陣的位置和方向。你如何在第一個地方找到矩陣?如果它稱作M,而L和F是兩種狀態,然後L.M = F所以M = INV(L).F

那是不夠具體? ;-)

+0

這正是我一直在這樣做之前,用旋轉矩陣的幫助。但它不起作用(圍繞[a,0,0]的旋轉可以,然後[0,b,0]也是,但是當我旋轉回來[-a,0,0],然後[0,-b, 0],相對距離不同)。這就是爲什麼我要求你舉個例子,以便我可以找出我犯的錯誤(我現在看不到)。另外,請注意它是3D(而不是2D)問題(無論如何應該有點類比)。 – PolGraphic 2014-10-18 14:35:59

+0

那麼,爲什麼不發佈我所建議的代碼,以便我們都可以嘗試發現錯誤? – 2014-10-18 14:39:41

+0

因爲我不希望你跟隨代碼並犯同樣的錯誤(=我不想讓你的錯誤)。但是,如你所願,我已經在問題下面發佈了我的代碼。 – PolGraphic 2014-10-18 14:48:40

相關問題