我有三個對象: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
以下sergeant
和sergeant
繼marshal
。所以,當,例如,marshal
動作,大家移動,並保持它們的距離(以及相對角度)彼此(以下簡稱「可視化」是2D的簡化,但我與3D模型的工作):
對於位置的變化,會做:
void Human::setPosition(XMFFLOAT3 newPosition){
position = newPosition;
for(auto &follower : followers){
follower.setPosition(newPosition - follower.distanceToFollow);
//keep the distance, soldier!
}
}
但我想不通,如何使旋轉相同?
當marshal
旋轉時,sergeant
將改變其position
和rotation
。
我幾次失敗後。在我最後一次嘗試,當我通過[40, 0, 0]
,然後[0, 30, 0]
,然後[-40, 0, 0]
和[0, -30, 0]
旋轉marshal
,sergeant
到位不同的結束,那麼所有這些旋轉(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;
}
這正是我一直在這樣做之前,用旋轉矩陣的幫助。但它不起作用(圍繞[a,0,0]的旋轉可以,然後[0,b,0]也是,但是當我旋轉回來[-a,0,0],然後[0,-b, 0],相對距離不同)。這就是爲什麼我要求你舉個例子,以便我可以找出我犯的錯誤(我現在看不到)。另外,請注意它是3D(而不是2D)問題(無論如何應該有點類比)。 – PolGraphic 2014-10-18 14:35:59
那麼,爲什麼不發佈我所建議的代碼,以便我們都可以嘗試發現錯誤? – 2014-10-18 14:39:41
因爲我不希望你跟隨代碼並犯同樣的錯誤(=我不想讓你的錯誤)。但是,如你所願,我已經在問題下面發佈了我的代碼。 – PolGraphic 2014-10-18 14:48:40