Directx - 局部轴上的矩阵转换

时间:2016-02-14 15:39:55

标签: c++ math matrix directx

我使用矩阵很困难

我可以像这样移动一个对象,旋转和以字符坐标移动:

  

matScale * matRotate * matTranslate

但我不知道如何在本地轴上移动物体 即:旋转后,移动(0,0,10)i对象的局部Z

编辑: 对不起,但我输了:(

我试过这个:

D3DXMatrixRotationX(&matRotateX, modell->getPitch());
    D3DXMatrixRotationY(&matRotateY, modell->getYaw());
    D3DXMatrixRotationZ(&matRotateZ, modell->getRoll());

    matRotate = matRotateX * matRotateY * matRotateZ; 




    D3DXMatrixScaling(&matScale, modell->getScale().x, modell->getScale().y, modell->getScale().z);



        Matrix WVP;
        WVP = matScale* matTranslate * matRotate * matView * matProjection;

        Matrix translation;
        D3DXMatrixTranslation(&translation, 10, 10, 0); // just for test


        cBuffer.Final = translation * WVP;

...但是旋转是围绕WORLD轴而不是本地:(

编辑2:

好的,我开始明白......我们现在可以:

- 使用以下方法在本地轴上翻译我的对象:

翻译* matRotate * matScale * matTranslate * matView * matProjection

“或”我们可以:

- 使用以下方法在本地轴上旋转此对象:

matRotate * translation * matScale * matTranslate * matView * matProjection

但是,我想同时进行两次转换^^,我想在<local>进行翻译,我希望使用相同的操作在<local>中进行转换

怎么可能? : - )

编辑3

好的,我认为我们可以简化......

我想移动物体的Z轴,我可以这样做:

if (input.keyPressed(VK_UP))
{
    ship->translate(0, 0, -0.01, ASF3D::LOCAL);

}

然后,我更新了他们班级中我的对象的位置:(功能:翻译)

position.x += z * sin(yaw);
position.y += z * sin(pitch);
position.z += z * -cos(yaw);

在此之后,我制作了matPosition(而不是管理位置矩阵和矩阵翻译)

然后,我做我的:cBuffer.Final = matScale * matRotate * matTranslate * matView * matProjection;

我无法测试atm,但我确信它正在运行且更容易 我只是不确定三角学的计算:P

1 个答案:

答案 0 :(得分:1)

注意:
这个答案并不特定于DirectX,它的一般矩阵乘法。但是,由于您没有提供任何代码或有关您如何解决问题的更多信息,因此这是我能想到的最好的。它应该让你在正确的轨道上完成如何使用矩阵进行变换。

首先是一些矩阵的一般关系:

M*N != N*M  //non-commutative
M*(N*O) = (M*N)*O  //associative
inverse(M*N) = inverse(N)*inverse(N)

S为缩放矩阵,R为旋转,T为翻译。进一步x是本地未转换坐标中的坐标,而w是世界坐标中的坐标。

如果将坐标从右侧乘以列向量,则可以得到如下内容:

w = S*R*T * x  <-> w = S*(R*(T*x))

首先在x的局部坐标中进行平移,然后在平移坐标中旋转,然后在平移和旋转坐标中进行缩放。通过将右边的'L'乘以当前的变换矩阵,可以轻松实现局部坐标系中的变换L

w = S*R*T * L * x  <-> w = S*(R*(T*(L*x)))

如果您修复为将其乘以左侧,则需要先使用某个矩阵M及其反I=inverse(M)进行变换,如下所示:

w = M*L*I * S*R*T * x

可以很容易地看到,M=(S*R*T)会变成:

w = (S*R*T) * L * inverse(S*R*T) * (S*R*T) * x
w = S*R*T * L * x

与上述相同。

如果您将坐标x乘以左侧的行向量,则上述公式将变为:

w = x * S*R*T <-> w = ((x*S)*R)*T

首先在x的局部坐标中缩放,然后在缩放的坐标中旋转,然后在缩放和旋转的坐标中进行平移。
(...)

w = x * L * S*R*T  <-> w = (((x*L)*S)*R)*T

(...)

w = x * S*R*T * I*L*M
w = x * (S*R*T) * inverse(S*R*T) * L * (S*R*T)
w = x * L * S*R*T
提供一些代码后

编辑

您的cBuffer.Final计算为:

cBuffer.Final = translation * WVP;

cBuffer.Final = translation * matScale* matTranslate * matRotate * matView * matProjection;

由于DirectX使用行向量,因此需要使用坐标x,然后首先应用translation,将对象移出中心。然后它应用matScale围绕坐标系中心缩放对象(因此进一步移动它)。然后它再次应用matTranslate移动它。然后它应用matRotate,围绕坐标系的中心旋转它(这将使对象以宽弧移动,因为您的对象不再居中)。然后它应用matView和最后matProjection来获取对象的屏幕坐标。

如果要围绕其局部坐标系旋转对象,请尝试以下操作:

cBuffer.Final = matRotate * translation * matScale * matTranslate * matView * matProjection;

这将首先旋转对象(当它仍在坐标系的中心时),然后应用(按顺序)translationmatScalematTranslate,{{ 1}}和matView

如果您(如编辑前的问题部分所述)想要沿着向量(0,0,10)在本地坐标中移动对象,请尝试:

matProjection

要注意的重要部分是:矩阵乘法的顺序决定了应用变换的顺序。即D3DXMatrixTranslation(&translation, 0, 0, 10); cBuffer.Final = translation * matRotate * matScale * matTranslate * matView * matProjection;

<强> EDIT2:
以评论中的宇宙飞船为例:

假设您的太空船有两个矩阵A*B != B*AmatPosition给出的位置和旋转。然后最终的转换矩阵由下式给出:

matRotate

(再看this image为什么我们先旋转然后翻译。)

然后,如果你想通过在z方向上移动位置5步来更新你的cBuffer.Final = matScale * matRotate * matPosition * matView * matProjection ,你会写:

matPosition

但是你想在局部z方向上移动它。所以你想要做的就是进行这种转变:

D3DXMatrixTranslation(&translation, 0, 0, 5);
matPosition *= translation;

其中(再次查看图片)将首先翻译,然后旋转(在局部轴上进行平移),然后将对象移动到其位置。然而,无论如何我们需要将这个平移“移动”到位置矩阵中,或者在下一步中它将使用我们不想要的新旋转矩阵。但我们可以将该行重写为(没有缩放,视图和项目):

cBuffer.Final = matScale * translation * matRotate * matPosition * matView * matProjection

这导致我们:

cBuffer.Final = translation * matRotate * matPosition

                /  This is the unity-matrix \ 
cBuffer.Final = matRotate * inverse(matRotate) * translation * matRotate * matPosition 
                            \ - - store this in a new position-matrix - - - - - - - /
cBuffer.Final = matRotate * matNewPosition