Directx-局部轴上的矩阵平移 [英] Directx - Matrix translation in local axis

查看:72
本文介绍了Directx-局部轴上的矩阵平移的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我很难使用矩阵

我可以像这样移动对象,旋转和在字坐标中移动:

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, Rthe 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;

这将首先旋转对象(当它仍然位于坐标系统的中心时),然后(按顺序)应用translationmatScalematTranslatematViewmatProjection.

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:

比方说,您的太空飞船具有由两个矩阵matPositionmatRotate给出的位置和旋转.然后,最终的变换矩阵为:

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆