繁体   English   中英

旋转矩阵 Java

[英]Rotation Matrix Java

我一直在学习创建游戏引擎的教程,当我开始计算 3D 旋转矩阵时,我遇到了我认为矩阵计算不正确的问题。 当我尝试在 x、y 和 z 轴上将矩阵旋转 0 度时,我应该得到旋转矩阵的单位矩阵,它应该如下所示:

Rotation Matrix:

1.0 0.0 0.0 0.0 
0.0 1.0 0.0 0.0 
0.0 0.0 1.0 0.0 
0.0 0.0 0.0 1.0

但我最终得到了一个如下所示的矩阵:

Rotation Matrix:

1.0 1.0 1.0 1.0 
1.0 1.0 1.0 1.0 
1.0 1.0 1.0 1.0 
1.0 1.0 1.0 1.0 

这是直接从教程中计算旋转矩阵的代码:

public class Matrix4f 
{
    private float[][] m;

    //generate a 4X4 array as my inital matrix which will represent homogeneous
    //coordinates: x, y, z, w
    public Matrix4f()
    {
        m = new float[4][4];
    }

    public Matrix4f initRotation(float x, float y, float z)
    {
        //generate rotation matrices for x, y, and z
        Matrix4f rx = new Matrix4f();
        Matrix4f ry = new Matrix4f();
        Matrix4f rz = new Matrix4f();

        //convert x,y, and z to radians for angle calculations
        x = (float)Math.toRadians(x);
        y = (float)Math.toRadians(y);
        z = (float)Math.toRadians(z);

        //calculate rotation matrices for x, y, z

        rz.m[0][0] = (float)Math.cos(z);rz.m[0][1] = (float)Math.sin(z);rz.m[0][2] = 0;             rz.m[0][3] = 0;
        rz.m[1][0] = -(float)Math.sin(z);rz.m[1][1] = (float)Math.cos(z);rz.m[1][2] = 0;                    rz.m[1][3] = 0;
        rz.m[2][0] = 0;                 rz.m[2][1] = 0;                 rz.m[2][2] = 1;                 rz.m[2][3] = 0;
        rz.m[3][0] = 0;                 rz.m[3][1] = 0;                 rz.m[3][2] = 0;                 rz.m[3][3] = 1;

        rx.m[0][0] = 1;                 rx.m[0][1] = 0;                 rx.m[0][2] = 0;                 rx.m[0][3] = 0;
        rx.m[1][0] = 0;                 rx.m[1][1] = (float)Math.cos(x);rx.m[1][2] = -(float)Math.sin(x);rx.m[1][3] = 0;
        rx.m[2][0] = 0;                 rx.m[2][1] = -(float)Math.sin(x);rx.m[2][2] = (float)Math.cos(x);rx.m[2][3] = 0;
        rx.m[3][0] = 0;                 rx.m[3][1] = 0;                 rx.m[3][2] = 0;                 rx.m[3][3] = 1;

        ry.m[0][0] = (float)Math.cos(y);ry.m[0][1] = 0;                 ry.m[0][2] = -(float)Math.sin(y);ry.m[0][3] = 0;
        ry.m[1][0] = 0;                 ry.m[1][1] = 1;                 ry.m[1][2] = 0;                 ry.m[1][3] = 0;
        ry.m[2][0] = (float)Math.sin(y);ry.m[2][1] = 0;                 ry.m[2][2] = (float)Math.cos(y);ry.m[2][3] = 0;
        ry.m[3][0] = 0;                 ry.m[3][1] = 0;                 ry.m[3][2] = 0;                 ry.m[3][3] = 1;

        //calculate the final rotation matrix by multiplying the 3 rotation matrices together
        m = rz.mul(ry.mul(rx)).getM();

        //a simple way to print out the full matrix
        System.out.println("Rotation Matrix:");
        for(int i = 0; i < 4; i++)
        {
            System.out.println("");
            for(int j = 0; j < 4; j++)
            {
                System.out.print(m[i][j] + " ");
            }
        }
        System.out.println("");

        return this;
    }

    //defining the multiplication operation for matrices
    public Matrix4f mul(Matrix4f r)
    {
        Matrix4f res = new Matrix4f();

        for(int i = 0; i < 4; i++)
        {
            for(int j = 0; j < 4; j++)
            {
                res.set(i, j, m[i][0]*r.get(0, i) + 
                              m[i][1]*r.get(1, i) +
                              m[i][2]*r.get(2, i) +
                              m[i][3]*r.get(3, i));
            }
        }

        return res;

    }

    //get the matrix in array form
    public float[][] getM() 
    {
        return m;
    }

    //get an individual element of the matrix
    public float get(int x, int y)
    {
        return m[x][y];
    }

    //set the whole matrix equal to a matrix m
    public void setM(float[][] m) 
    {
        this.m = m;
    }

    //set an individual element of the matrix to a value
    public void set(int x, int y, float value)
    {
        m[x][y] = value;
    }

}

然后基本上当我尝试像这样在 main 方法中运行它时:

(new Matrix4f()).initRotation(0, 0, 0);

我得到

Rotation Matrix:

1.0 1.0 1.0 1.0 
1.0 1.0 1.0 1.0 
1.0 1.0 1.0 1.0 
1.0 1.0 1.0 1.0

即使根据旋转矩阵运算我应该得到:

Rotation Matrix:

1.0 0.0 0.0 0.0 
0.0 1.0 0.0 0.0 
0.0 0.0 1.0 0.0 
0.0 0.0 0.0 1.0

编辑:经过一些更多的调试,我在更多的调试后解决了矩阵 mul 方法中的问题。 我为我的懒惰道歉。 我已经编程一段时间了,我真的不经常做这种事情,但我对我的程序感到非常沮丧。

矩阵乘法算法的修正为:

public Matrix4f mul(Matrix4f r)
    {
        Matrix4f res = new Matrix4f();

        for(int i = 0; i < 4; i++)
        {
            for(int j = 0; j < 4; j++)
            {
                res.set(i, j, m[i][0]*r.get(0, j) + 
                              m[i][1]*r.get(1, j) +
                              m[i][2]*r.get(2, j) +
                              m[i][3]*r.get(3, j));
            }
        }

        return res;

    }

代替:

公共 Matrix4f mul(Matrix4f r) { Matrix4f res = new Matrix4f();

    for(int i = 0; i < 4; i++)
    {
        for(int j = 0; j < 4; j++)
        {
            res.set(i, j, m[i][0]*r.get(0, i) + 
                          m[i][1]*r.get(1, i) +
                          m[i][2]*r.get(2, i) +
                          m[i][3]*r.get(3, i));
        }
    }

    return res;

}
  • 我认为你的乘法函数在逻辑上是不正确的。 在您的乘法函数中,您最终将每个单元格的第一个原始列和列相乘。 如下所示将 i 更改为 j 将正确计算乘法。

     public Matrix4f mul(Matrix4f r) { Matrix4f res = new Matrix4f(); for(int i = 0; i < 4; i++) { for(int j = 0; j < 4; j++) { res.set(i, j, m[i][0]*r.get(0, j) + m[i][1]*r.get(1, j) + m[i][2]*r.get(2, j) + m[i][3]*r.get(3, j)); } } return res; }
  • 其次,您可以尝试使用乘法函数中的断点来调试代码。 您可以使用任何标准 IDE (Eclipse) 调试功能进行调试。 您将逐步获得正确的执行思路,然后您将能够自己更正代码。

希望能帮助到你。

我做了很多调试,我发现你有错误的索引:

res.set(i, j, m[i][0]*r.get(0, i) + 
    m[i][1]*r.get(1, i) +
    m[i][2]*r.get(2, i) +
    m[i][3]*r.get(3, i));

你在两个矩阵上都有索引i - 你应该这样修复它:

res.set(i, j, m[i][0]*r.get(0, j) + 
    m[i][1]*r.get(1, j) +
    m[i][2]*r.get(2, j) +
    m[i][3]*r.get(3, j));

如果您在接下来的计算中收到转置矩阵(在单位矩阵上无法弄清楚) - 交换ij希望它有帮助;)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM