Directx-局部轴上的矩阵平移 [英] Directx - Matrix translation in local axis
问题描述
我很难使用矩阵
我可以像这样移动对象,旋转和在字坐标中移动:
I can move an object, rotate, and move in word coordinate like these:
matScale * matRotate * matTranslate
matScale* matRotate * matTranslate
但是我不知道如何在其局部轴上移动对象 即:旋转后,将(0,0,10)移动到对象的本地Z
But I don't know how to move an object in his local axis i.e: after rotate, move(0,0,10) i local Z of the object
抱歉,我迷路了:(
我已经尝试过了:
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轴,而不是本地:(
...but the rotation is around WORLD axis, not local :(
好的,我开始了解…我们现在可以:
OK, I begin to understand… we can now:
-使用以下方法在本地轴上平移对象:
-Translate my object in local axis with:
翻译* matRotate * matScale * matTranslate * matView * matProjection
translation * matRotate * matScale * matTranslate * matView * matProjection
或"我们可以:
-使用以下方法在局部轴上旋转该对象:
-Rotate this object on local axis with:
matRotate *翻译* matScale * matTranslate * matView * matProjection
matRotate * translation * matScale * matTranslate * matView * matProjection
但是,我想同时进行两个转换^^,我想在<local>
中进行翻译,并且想在<local>
中进行相同的操作
But, I want to do the two transformation in same time ^^, I want to translate in <local>
AND I want to rotate in <local>
with the same operation
怎么可能? :-)
编辑3
好的,我想我们可以简化一下...
Okay, I think we can simplify that...
我想在对象的Z轴上移动,我可以这样做:
I want to move on Z axis of the object, I can do that:
if (input.keyPressed(VK_UP))
{
ship->translate(0, 0, -0.01, ASF3D::LOCAL);
}
然后,我更新对象在其类中的位置:(功能:翻译)
Then, I update positions of my objects in their class: (fuction: translate)
position.x += z * sin(yaw);
position.y += z * sin(pitch);
position.z += z * -cos(yaw);
此后,我将执行matPosition(而不是管理位置矩阵和矩阵平移)
After this, I make my matPosition (Instead of managing a location matrix and a matrix tranlation)
然后,我做我的:cBuffer.Final = matScale * matRotate * matTranslate * matView * matProjection;
Then, I do my: cBuffer.Final = matScale* matRotate * matTranslate* matView * matProjection;
我无法测试atm,但我确定它可以正常工作并且更容易
我只是不确定三角函数的计算:P
I can't test atm, but I'm sure it's working and it easier
I'm just not sure about the calculations of trigonometry :P
推荐答案
注意:
这个答案不是特定于DirectX的,它是关于一般矩阵乘法的.但是,由于您没有提供任何代码或有关如何解决问题的更多信息,这是我能提供的最好的解决方案.并且它应该使您正确地进行矩阵转换.
Note:
This answer is not specific to DirectX, its about general matrix multiplication. But since you didn`t provide any code or any more information about how you tried to solve the problem, it's the best i can come up with. And it should get you on the right track how transformations with matrices are done.
首先是矩阵的一般关系:
First some general relations of matrices:
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
是世界坐标的坐标.
Let S
be the scaling matrix, R
the rotation and T
the translation. Further x
are the coordinates in local, untransformed coordinates while w
are the coordinates in world coordinates.
如果从右边乘以坐标作为列向量,则会得到类似的内容
If you multiply coordinates as column-vector from the right, you get something like:
w = S*R*T * x <-> w = S*(R*(T*x))
它将首先在x的局部坐标中平移,然后在平移的坐标中旋转,然后在平移和旋转的坐标中缩放.通过将右边的L乘以当前的变换矩阵,可以轻松地实现局部坐标系中的变换L
:
which first translates in the local coordinates of x, then rotates in the translated coordinates, then scales in the translated and rotated coordinates. A transformation L
in the local coordinate-system can be easily achieved by multiplying 'L' from the right to your current transformation matrix:
w = S*R*T * L * x <-> w = S*(R*(T*(L*x)))
如果已固定为将其与左侧相乘,则需要先使用一些矩阵M
及其反矩阵I=inverse(M)
对其进行变换,如下所示:
if you are fixed to multiply it to the left, you need to transform it first with some matrix M
and its inverse I=inverse(M)
like this:
w = M*L*I * S*R*T * x
一个人可以很容易地看到,使用M=(S*R*T)
,它变为:
one can easily see, that with M=(S*R*T)
this becomes:
w = (S*R*T) * L * inverse(S*R*T) * (S*R*T) * x
w = S*R*T * L * x
与上面相同.
如果将坐标x
乘以左侧的行向量,则上述公式将变为:
If you multiply your coordinates x
as a row-vector from the left, the above formulas become:
w = x * S*R*T <-> w = ((x*S)*R)*T
首先在x的局部坐标中缩放,然后在缩放的坐标中旋转,然后在缩放和旋转的坐标中平移.
(...)
which first scales in the local coordinates of x, then rotates in the scaled coordinates, then translates in the scaled and rotated coordinates.
(...)
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
提供一些代码后,
编辑:
Edit after you provided some code:
您的cBuffer.Final
的计算公式为:
cBuffer.Final = translation * WVP;
或
cBuffer.Final = translation * matScale* matTranslate * matRotate * matView * matProjection;
由于DirectX使用行向量,因此将获取坐标x
,然后首先应用translation
,将对象移出中心.然后,它应用matScale
围绕坐标系的中心缩放对象(并因此将其进一步移动).然后应用matTranslate
再次移动它.然后应用matRotate
,围绕坐标系统的中心旋转它(由于对象不再居中,这将使对象以较大的弧度移动).然后,它应用matView
并最终应用matProjection
来获取对象的屏幕坐标.
Since DirectX uses row-vectors, this takes your coordinates x
and then first applies translation
, moving the object out of the center. Then it applies matScale
scaling the Object around the center of your coordinate-system (and therefore moving it even further). Then it applies matTranslate
moving it again. Then it applies matRotate
, rotating it around the center of your coordinate system (this will move the object in a wide arc, since your object is not centered anymore). Then it applies the matView
and finally matProjection
to get the screen-coordinates of your object.
如果要围绕对象的局部坐标系旋转对象,请尝试以下操作:
If you want to rotate the object around its local coordinate system, try this:
cBuffer.Final = matRotate * translation * matScale * matTranslate * matView * matProjection;
这将首先旋转对象(当它仍然位于坐标系统的中心时),然后(按顺序)应用translation
,matScale
,matTranslate
,matView
和matProjection
.
This will first rotate the object (while it is still in the center of your coordinate system) and then apply (in order) the translation
, matScale
, matTranslate
, matView
and matProjection
.
如果您(如在编辑之前的问题部分所述)要沿矢量(0,0,10)在局部坐标中移动对象,请尝试以下操作:
If you (as stated in the part of your question before the edit) want to move your object in local coordinates along the vector (0,0,10), try this:
D3DXMatrixTranslation(&translation, 0, 0, 10);
cBuffer.Final = translation * matRotate * matScale * matTranslate * matView * matProjection;
需要注意的重要部分是:矩阵乘法的顺序决定了应用转换的顺序. IE. A*B != B*A
The importan part to note is: The order of your matrix-multiplications determines the order in which transformations are applied. I.e. A*B != B*A
以评论中的太空飞船为例:
To take the example with the spaceship from comment:
比方说,您的太空飞船具有由两个矩阵matPosition
和matRotate
给出的位置和旋转.然后,最终的变换矩阵为:
Let's say your spaceship has a position and a rotation given by 2 matrices matPosition
and matRotate
. Then the final transformation matrix is given by:
cBuffer.Final = matScale * matRotate * matPosition * matView * matProjection
(再次参见此图像为什么我们先旋转然后平移.)
(See again this image why we first rotate and then translate.)
然后,如果要通过在z方向上移动位置5步来更新matPosition
,则应编写:
Then if you want to update your matPosition
by moving the position 5 steps in z-direction you would write:
D3DXMatrixTranslation(&translation, 0, 0, 5);
matPosition *= translation;
但是您想在本地z方向上移动它.因此,您要做的就是进行以下转换:
But you want to move it in the local z-direction. So what you want to do is to have this transformation:
cBuffer.Final = matScale * translation * matRotate * matPosition * matView * matProjection
先(平移图片),然后平移,然后旋转(在局部轴上平移),然后将对象移动到其位置.但是,无论如何,我们都需要将此平移移动"到位置矩阵中,或者在下一步中,它将使用我们不希望的新旋转矩阵.但是我们可以将行改写为(没有缩放,视图和项目):
Which (look at the picture again) will first translate, then rotate (giving a translation in local axis) and then move the object to its position. However we anyhow need to "move" this translation into the position-matrix or in the next step it will use the new rotation matrix, which we dont want. But we can rewrite the line as (without scale, view and project):
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
这导致我们:
D3DXMatrixTranslation(&translation, 0, 0, 5);
matPosition = inverse(matRotate) * translation * matRotate * matPosition;
cBuffer.Final = matScale * matRotate * matPosition * matView * matProjection;
这篇关于Directx-局部轴上的矩阵平移的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!