2014-10-18 104 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