如何应用的变换矩阵? [英] How to apply a transformation matrix?

查看:147
本文介绍了如何应用的变换矩阵?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想获得在三维空间中的点的2D屏幕坐标,即我知道摄像机的平移,倾斜和滚动的位置,我有3D X,Y,一个点我想Z坐标项目。

I am trying to get the 2D screen coordinates of a point in 3D space, i.e. I know the location of the camera its pan, tilt and roll and I have the 3D x,y,z coordinates of a point I wish to project.

我有困难理解转型/投影矩阵,我希望一些聪明的人在这里可以帮助我一起;)

I am having difficulty understanding transformation/projection matrices and I was hoping some intelligent people here could help me along ;)

下面是我的测试code我都扔在一起迄今:

Here is my test code I have thrown together thus far:

public class TransformTest {

public static void main(String[] args) {

    // set up a world point (Point to Project)
    double[] wp = {100, 100, 1};
    // set up the projection centre (Camera Location)
    double[] pc = {90, 90, 1};

    double roll = 0;
    double tilt = 0;
    double pan = 0;

    // translate the point
    vSub(wp, pc, wp);

    // create roll matrix
    double[][] rollMat = {
            {1, 0, 0},
            {0, Math.cos(roll), -Math.sin(roll)},
            {0, Math.sin(roll), Math.cos(roll)},
    };
    // create tilt matrix
    double[][] tiltMat = {
            {Math.cos(tilt), 0, Math.sin(tilt)},
            {0, 1, 0},
            {-Math.sin(tilt), 0, Math.cos(tilt)},
    };
    // create pan matrix
    double[][] panMat = {
            {Math.cos(pan), -Math.sin(pan), 0},
            {Math.sin(pan), Math.cos(pan), 0},
            {0, 0, 1},
    };

    // roll it
    mvMul(rollMat, wp, wp);
    // tilt it
    mvMul(tiltMat, wp, wp);
    // pan it
    mvMul(panMat, wp, wp);

}

public static void vAdd(double[] a, double[] b, double[] c) {
    for (int i=0; i<a.length; i++) {
        c[i] = a[i] + b[i];
    }
}

public static void vSub(double[] a, double[] b, double[] c) {
    for (int i=0; i<a.length; i++) {
        c[i] = a[i] - b[i];
    }      
}

public static void mvMul(double[][] m, double[] v, double[] w) {

    // How to multiply matrices?
} }

基本上,我需要的是让二维的XY坐标给定的屏幕,其中三维点相交。我不知道如何使用滚动,倾斜和平移矩阵来改造世界点(WP)。

Basically, what I need is to get the 2D XY coordinates for a given screen where the 3D point intersects. I am not sure how to use the roll, tilt and pan matrices to transform the world point (wp).

任何帮助,这是极大的AP preciated!

Any help with this is greatly appreciated!

推荐答案

这是复杂的东西。请阅读一本关于这个话题让所有的数学和细节问题的详细信息。如果你打算用这个东西在长打,你需要知道这些事情。这个答案就是如此,你可以让你的脚湿和黑客左右。

首先最重要的。矩阵乘法是一个相当简单的事

First things first. Multiplying matrices is a reasonably simple affair.

让我们假设你有矩阵的 A B C 的,其中的 AB = ç 的。比方说,你想弄清楚矩阵的 C 的值在第3行,第2列。

Let's say you have matrices A, B, and C, where AB = C. Let's say you want to figure out the value of matrix C at row 3, column 2.

  • 取的 A 的第三行中的 B 的第二列。你应该有价值观相同数量从 A B 的现在。 (如果您没有矩阵乘法没有被定义为这两个矩阵。你不能这样做。)如果两个都是4×4矩阵,你应该从 A 的4个值(行3 )和4个值的 B 的(第2列)。
  • 乘法的 A 的每个值的每个值的 B 的。您应该结束了4个新的值。
  • 在添加这些值。
  • Take the third row of A and the second column of B. You should have the same number of values from A and B now. (If you don't matrix multiplication isn't defined for those two matrices. You can't do it.) If both are 4×4 matrices, you should have 4 values from A (row 3) and 4 values from B (column 2).
  • Multiply each value of A with each value of B. You should end up with 4 new values.
  • Add these values.

您现在有矩阵的 C 的在第3行的值,列2所面临的挑战是,当然,要做到这一点编程。

You now have the value of matrix C at row 3, column 2. The challenge is, of course, to do this programmatically.

/* AB = C

Row-major ordering
a[0][0] a[0][2] a[0][3]...
a[1][0] a[1][4] ...
a[2][0] ...
...*/
public static mmMul(double[][] a, double[][] b, double[][] c) {
    c_height = b.length; // Height of b
    c_width = a[0].length; // Width of a
    common_side = a.length; // Height of a, width of b

    for (int i = 0; i < c_height; i++) {
        for (int j = 0; j < c_width; j++) {
            // Ready to calculate value of c[i][j]
            c[i][j] = 0;

            // Iterate through ith row of a, jth col of b in lockstep
            for (int k = 0; k < common_side; k++) {
                c[i][j] += a[i][k] * b[k][j];
            }
        }
    }
}



您有3D坐标。比方说,你有(5,2,1)。这是笛卡儿坐标。让我们把他们(的 X 以Z 的)。

You have 3D coordinates. Let's say you have (5, 2, 1). These are Cartesian coordinates. Let's call them (x, y, z).

同质的坐标意味着你写一个额外的1在您的笛卡尔坐标的末端。 (5,2,1)变成(5,2,1,1)。让我们把他们(的 X 以Z 是W 的)。

Homogenous coordinates mean that you write an extra 1 at the end of your Cartesian coordinates. (5, 2, 1) becomes (5, 2, 1, 1). Let's call them (x, y, z, w).

每当你做一个转变,使的是W 的≠1,你把你的坐标,​​每一个组件通过的是W 的。这改变了你的 X 以Z 的,它使的是W = 1再次。 (有没有这样做,伤害甚至当你的转换不会改变的是W 的,它只是由1分一切,这不执行任何操作。)

Whenever you do a transformation that makes w ≠ 1, you divide every component of your coordinates by w. This changes your x, y, and z, and it makes w = 1 again. (There is no harm in doing this even when your transformation doesn't change w. It just divides everything by 1, which does nothing.)

有一些majorly很酷的东西,你可以用齐次坐标做,即使他们背后的数学不会使总感觉。正是在这一点上,我要求你们在建议重新审视这个答案的上方。

There is some majorly cool stuff you can do with homogenous coordinates, even if the math behind them doesn't make total sense. It is at this point that I ask you to look again at the advice at the top of this answer.


我将使用OpenGL的术语和方法,这一点,下面的章节。如果有什么不清楚或似乎与你的目标相冲突(因为这似乎隐约功课似的对我说:P),请发表评论。

I'll be using OpenGL terminology and approaches in this and following sections. If anything is unclear or seems to conflict with your goals (because this seems vaguely homework-like to me :P), please leave a comment.

我也假设你的侧倾,俯仰和平移矩阵是正确的开始。

I'll also start by assuming that your roll, tilt, and pan matrices are correct.

当你想使用一个转换矩阵的一个点,你右乘以矩阵的列向量重新presenting你的观点。假设你要翻译(5,2,1)通过一些变换矩阵的 A 的。首先定义的 v 的= [5,2,1,1] T 。 (我写的[ X 以Z 是W 的] T 小牛逼以表示的的应该把它作为一个列向量。)

When you want to transform a point using a transformation matrix, you right-multiply that matrix with a column vector representing your point. Say you want to translate (5, 2, 1) by some transformation matrix A. You first define v = [5, 2, 1, 1]T. (I write [x, y, z, w]T with the little T to mean that you should write it as a column vector.)

// Your point in 3D
double v[4][5] = {{5}, {2}, {1}, {1}}

在这种情况下,的 AV = v 的<分> 1 ,其中的 v 的<分> 1 是你的变换点。这样做乘法就像一个矩阵乘法,其中的 A 的是4×4的 v 的是4×1。你会最终有一个4×1矩阵(这是另一个列向量)。

In this case, Av = v1, where v1 is your transformed point. Do this multiplication like a matrix multiplication, where A is 4×4 and v is 4×1. You will end up with a 4×1 matrix (which is another column vector).

// Transforming a single point with a roll
double v_1[4][6];
mmMul(rollMat, v, v_1);

现在,如果你有几个变换矩阵应用,首先将它们组合成一个转换矩阵。按照您希望他们应用矩阵一起在为了乘做到这一点。

Now, if you have several transformation matrices to apply, first combine them into one transformation matrix. Do this by multiplying the matrices together in the order that you want them applied.

编程,你应该从单位矩阵和右乘以每个变换矩阵。让我们的 I 的<子> 4 4×4矩阵,并让的 A 的<分> 1 , A 2 A 的<子> 3 ,...是你的变换矩阵。让你的最后一个变换矩阵是的 A 的<子>最后

Programmatically, you should start with the identity matrix and right-multiply each transformation matrix. Let I4 be 4×4 identity matrix, and let A1, A2, A3, ... be your transformation matrices. Let your final transformation matrix be Afinal

A 的<子>最后← I 的<子> 4
A 的<子>最后← A 的<子>最后的 A 的<分> 1 < BR> A 的<子>最后← A 的<子>最后的 A 2 < BR> A 的<子>最后← A 的<子>最后的 A 的<子> 3 < BR>

AfinalI4
AfinalAfinal A1
AfinalAfinal A2
AfinalAfinal A3

请注意,我用的箭头,​​重新present分配。当你实现这一点,一定要确保不覆盖的<子>最后的当你还在使用它的矩阵乘法计算!制作副本。

// A composite transformation matrix (roll, then tilt)

double a_final[4][4] =
{
    {1, 0, 0, 0},
    {0, 1, 0, 0},
    {0, 0, 1, 0},
    {0, 0, 0, 1}
}; // the 4 x 4 identity matrix

double a_final_copy[4][4];
mCopy(a_final, a_final_copy); // make a copy of a_final
mmMul(rollMat, a_final_copy, a_final);
mCopy(a_final, a_final_copy); // update the copy
mmMul(tiltMat, a_final_copy, a_final);

最后,做同样的乘法上面: A 的<子>最后的 v = v 的<分> 1

// Use the above matrix to transform v
mmMul(a_final, v, v_1);



相机转换应该是psented作为视图矩阵重新$ P $。在这里对您的的 A 的<子>查看的 v = v 的<分> 1 操作。 ( v 的再presents你的世界坐标为4×1列向量的 A 的<子>最后是 A <子>查看)

Camera transformations should be represented as a view matrix. Perform your Aview v = v1 operation here. (v represents your world coordinates as a 4×1 column vector, Afinal is your Aview.)

// World coordinates to eye coordinates
// A_view is a_final from above
mmMult(a_view, v_world, v_view);

投影变换描述一个透视变换。这是什么使接近的物体更大,更远的对象小。这是在相机变换之后进行。如果你不想要的角度来看呢,只是使用单位矩阵为投影矩阵。无论如何,执行的 A V 的<分> 1 = v 2 在这里。

Projection transformations describe a perspective transform. This is what makes nearer objects bigger and farther objects smaller. This is performed after the camera transformation. If you don't want perspective yet, just use the identity matrix for the projection matrix. Anyway, perform A v1 = v2 here.

// Eye coordinates to clip coordinates
// If you don't care about perspective, SKIP THIS STEP
mmMult(a_projection, v_view, v_eye);

接下来,你需要做透视鸿沟。这再往更深的齐次坐标,而我还没有描述。总之,通过的 v 2 的最后一个组成部分划分的的 v 2 的每个组件。如果的 v 2 = [ X 以Z W¯¯ 的] T ,然后通过的将每个成分w 的(含的是W 的本身)。您应该结束了的是W = 1(如果你的投影矩阵为单位矩阵,就像我前面所述,这一步应该什么都不做。)

Next, you need to do a perspective divide. This delves deeper into homogenous coordinates, which I haven't described yet. Anyway, divide every component of v2 by the last component of v2. If v2 = [x, y, z, w]T, then divide each component by w (including w itself). You should end up with w = 1. (If your projection matrix is the identity matrix, like I described earlier, this step should do nothing.)

// Clip coordinates to normalized device coordinates
// If you skipped the previous step, SKIP THIS STEP
for (int i = 0; i < 4; i++) {
    v_ndc[i] = v_eye[i] / v[3];
}

最后,把你的 v 2 。前两个坐标是你的 X 的坐标。三是以Z 的,你可以扔掉。 (后来,一旦你得到非常先进的,你可以用这个的以Z 的值,以找出哪些点是在前面或后面的某个点。)在这一点上,最后一个组件是的是W = 1,所以你并不需要,在所有了。

Finally, take your v2. The first two coordinates are your x and y coordinates. The third is z, which you can throw away. (Later, once you get very advanced, you can use this z value to figure out which point is in front of or behind some other point.) And at this point, the last component is w = 1, so you don't need that at all anymore.

x = v_ndc[0]
y = v_ndc[1]
z = v_ndc[2]  // unused; your screen is 2D

如果你跳过了视角和透视分割步骤,使用 v_view 而不是 v_ndc 以上。

If you skipped the perspective and perspective divide steps, use v_view instead of v_ndc above.

这是非常相似的一组 OpenGL的坐标系。不同的是,你开始与世界坐标,而OpenGL的开始,目标坐标。所不同的是,如下所示:

This is very similar to the set of OpenGL coordinate systems. The difference is that you start with world coordinates, while OpenGL starts with object coordinates. The difference is as follows:

  • 您开始与世界坐标
    • 在OpenGL的开始,目标坐标
    • You start with world coordinates
      • OpenGL starts with object coordinates
      • OpenGL的使用模型视图矩阵将目标坐标眼坐标

      从那里,一切都是一样的。

      From there on, everything is the same.

      这篇关于如何应用的变换矩阵?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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