我使用矩阵很困难
我可以像这样移动一个对象,旋转和以字符坐标移动:
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
答案 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;
这将首先旋转对象(当它仍在坐标系的中心时),然后应用(按顺序)translation
,matScale
,matTranslate
,{{ 1}}和matView
。
如果您(如编辑前的问题部分所述)想要沿着向量(0,0,10)在本地坐标中移动对象,请尝试:
matProjection
要注意的重要部分是:矩阵乘法的顺序决定了应用变换的顺序。即D3DXMatrixTranslation(&translation, 0, 0, 10);
cBuffer.Final = translation * matRotate * matScale * matTranslate * matView * matProjection;
强>
<强> EDIT2:强>
以评论中的宇宙飞船为例:
假设您的太空船有两个矩阵A*B != B*A
和matPosition
给出的位置和旋转。然后最终的转换矩阵由下式给出:
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