我有三个对象: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