Java 使用Matrix4f绕多个轴旋转长方体

Java 使用Matrix4f绕多个轴旋转长方体,java,opengl,matrix,vector,rotation,Java,Opengl,Matrix,Vector,Rotation,问题有点变,我知道如何绕一个轴旋转了 我想使用一个角度绕Y轴旋转一个长方体。 该框有一个大小和一个矢量3f来表示旋转 要正确旋转长方体,我要做的是旋转原点位置,然后旋转原点位置加上大小,并使用这两个参照渲染长方体 但是,此旋转无法正常工作,并导致渲染瑕疵 这是我旋转位置的代码: Matrix4f matrix = new Matrix4f(); // Rotate the origin position Vector3f pos = new Vector3f(new V

问题有点变,我知道如何绕一个轴旋转了

我想使用一个角度绕Y轴旋转一个长方体。 该框有一个大小和一个矢量3f来表示旋转

要正确旋转长方体,我要做的是旋转原点位置,然后旋转原点位置加上大小,并使用这两个参照渲染长方体

但是,此旋转无法正常工作,并导致渲染瑕疵

这是我旋转位置的代码:

    Matrix4f matrix = new Matrix4f();

    // Rotate the origin position
    Vector3f pos = new Vector3f(new Vector3f(blockX, blockY, blockZ));

    matrix.m03 = pos.x;
    matrix.m13 = pos.y;
    matrix.m23 = pos.z;

    Vector3f rot = new Vector3f(new Vector3f(0, 1f, 0f));

    Matrix4f.rotate((float) Math.toRadians(45f), rot, matrix, matrix);

    Vector3f locationMin = new Vector3f(matrix.m03, matrix.m13, matrix.m23);

    // Rotate the position with the size
    // Top left back is the position of the block
    Vector3f sizeRot = new Vector3f(new Vector3f(blockX + size, blockY + size, blockZ + size));
    matrix = new Matrix4f();

    matrix.m03 = sizeRot.x;
    matrix.m13 = sizeRot.y;
    matrix.m23 = sizeRot.z;

    rot = new Vector3f(new Vector3f(0, 1f, 0f));

    Matrix4f.rotate((float) Math.toRadians(45f), rot, matrix, matrix);

    Vector3f locationMax = new Vector3f(matrix.m03, matrix.m13, matrix.m23);

    // Then here I use the locationMax and the locationMin to render the cube
此代码可能有什么问题?我用来旋转盒子的逻辑正确吗?如中所述,旋转原点位置,然后旋转原点位置加上尺寸

编辑:我发布了翻译后旋转是愚蠢的,因此我只是旋转了未翻译的locationMax(只是大小),然后我翻译了,仍然得到相同的结果(图形瑕疵)

新代码:

    float rx = blockX, ry = blockY, rz = blockZ;
    Matrix4f matrix = new Matrix4f();

    Vector3f rot = new Vector3f(0, 1f, 0f);
    matrix = new Matrix4f();

    matrix.m03 = size;
    matrix.m13 = size;
    matrix.m23 = size;

    Matrix4f.rotate((float) Math.toRadians(45f), rot, matrix, matrix);
    matrix.translate(new Vector3f(rx, ry, rz), matrix);

    float mx = matrix.m03;
    float my = matrix.m13;
    float mz = matrix.m23;
    // Here is use rx, ry, rz and mx, my, mz to render the box
==================*我想出来了(见下文)*=============

编辑:

这就是我最后做的:

    // Origin point
    Vector4f a = new Vector4f(blockX, blockY, blockZ, 1);

    // Rotate a matrix 45 degrees
    Matrix4f mat = new Matrix4f();
    mat.rotate((float) Math.toRandians(45f), new Vector3f(
            0, 1f, 0), mat);

    /* Transform the matrix to each point */

    Vector4f c = new Vector4f(size.x, 0, size.z, 1);
    Matrix4f.transform(mat, c, c);
    Vector4f.add(c, a, c);

    Vector4f b = new Vector4f(size.x, 0, 0, 1);
    Matrix4f.transform(mat, b, b);
    Vector4f.add(b, a, b);

    Vector4f d = new Vector4f(0, 0, size.z, 1);
    Matrix4f.transform(mat, d, d);
    Vector4f.add(d, a, d);

    // Here is use a, b, c, and d to render the box.
问题是我想绕所有轴旋转,而不仅仅是绕Y轴旋转。这使得代码非常长且不可读,当我尝试围绕所有轴旋转时,会出现很多错误

更新问题:

我如何获取上面的代码并使其能够围绕所有3个轴旋转。我想这样做,这样我就可以有一个广告牌,将始终面对镜头

这是我如何计算相机和对象之间的角度:

    Vector3f angle = new Vector3f();
    // Calculate the distance between camera and object
    Vector3f.sub(game.getCamera().getLocation(),
            new Vector3f(blockX, blockY, blockZ), angle);

    // Calculate the angle around the Y axis.
    float vectorAngle = (float) ((float) Math.atan2(angle.z, angle.x) * -1 + (Math.PI / 2.0f));
是计算机图形学的一个非常常见的应用程序(我相信你已经注意到了,因为你在问这个问题!)

最终,我认为你把问题复杂化了,因为:

如中所述,旋转原点位置,然后旋转原点位置加上尺寸

对于计算机图形学来说,最常见的变换是缩放、平移和旋转,并且执行这些变换是为了获得所需的效果(通常是缩放,然后围绕原点旋转,然后平移顶点的位置)

此外,您将有三个主要矩阵以三维方式渲染模型:世界矩阵、视图矩阵和投影矩阵。我相信你对从模型空间到世界空间的转换有误解

。如果你有概念上的问题,或者这个答案是不够的,我强烈建议你看看这个链接。我还没有找到更好的资源来解释计算机图形学的基础知识

现在,你的三个角度(以度为单位,矢量3)对应于广告牌和相机在X、Y和Z坐标空间的角度差。利用这些信息,我们首先将所有矩阵变换收集到一个位置,从而生成视图矩阵

我假设你已经有了平移矩阵和缩放矩阵,它们都能工作。这意味着我们只需要生成旋转矩阵,然后用缩放矩阵变换该矩阵,然后用平移矩阵变换该矩阵

X旋转矩阵

Y旋转矩阵

Z旋转矩阵

(图片取自上面的CodingLabs链接)

因此,您将使用前面计算的X、Y和Z角度生成这三个矩阵,然后将它们转换为单个矩阵,通过缩放矩阵转换该矩阵,然后通过平移矩阵转换该矩阵。现在你有了一个很棒的矩阵,当你将一个顶点乘以它时,它将把这个顶点变换成所需的大小、旋转和位置

所以你用这个生成的矩阵变换每个顶点

在那之后,你就应该完蛋了!使用这些技术有望大大简化您的代码,并使您走上正确的道路:)

那么现在来点代码怎么样

//I do not guarantee that this code compiles! I did not write it in an IDE nor did I compile it
float angleToRotX = 180f;
float angleToRotY = 90f;
float angleToRotZ = 0f;

// example vertex
Vector4f vertex = new Vector4f(0, 1, 0, 1);

// Rotate vertex's X coordinates by the desired degrees
Matrix4f rotationXMatrix = new Matrix4f();
rotationXMatrix.rotX(angleToRotX);

Matrix4f rotationYMatrix = new Matrix4f();
rotationYMatrix.rotY(angleToRotY);

Matrix4f rotationZMatrix = new Matrix4f();
rotationZMatrix.rotZ(angleToRotZ);

//now let's translate it by 1.5, 1, 1.5 in the X,Y,Z directions
Matrix4f translationMatrix = new Matrix4f();
translationMatrix.setTranslate(new Vector3f(1.5, 1, 1.5));

/*
Now we have our three rotational matrices. So we multiply them (transform them) to get a single matrix to transform all of the points in this model to the desired world coordinates

*/
Matrix4f rotationMatrix = new Matrix4f();
rotationMatrix.mul(rotationXMatrix);
rotationMatrix.mul(rotationYMatrix);
rotationMatrix.mul(rotationZMatrix);

Matrix4f worldMatrix = translationMatrix;
worldMatrix.mul(rotationMatrix);

//now worldMatrix, when applied to a vertex, will rotate it by X,Y,Z degrees about the origin of it's model space, and then translate it by the amount given in translationMatrix

worldMatrix.transform(vertex);

//now vertex should be (1.5, 0, 1.5, 1) with (x,y,z,1)
现在这段代码真的可以简化了,而且过于冗长。试试看!我没有在我的机器上下载java,但是我从java文档中获取了这些方法

下面是正在发生的事情的图像(同样,取自编码实验室):


(高级信息:。这些是在3d空间中定向模型的非常酷的方法,但是我不太理解它们,我需要向其他人解释它,我也相信你的问题更基本)

你可以轻松生成矩阵。OpenGL矩阵如下所示:

|lx,ux,vx,px|    - lx,ly,lz = the left vector
|ly,uy,vy,py|    - ux,uy,uz = the up vector
|lz,uz,vz,pz|    - vx,vy,vz = the view vector
|0 ,0 ,0 ,1 |    - px,py,pz = the translation
你所需要做的就是将px,py,pz设置为你的盒子在世界上的位置, 将视图向量设置为标准化(摄影机位置-框位置),向上直接来自摄影机,左侧通过标准化叉积计算。在左向量(通过另一个叉积)导出后,重建上向量也是一种很好的做法。就这些


我的解决方案旨在为您节省一些编码时间,而不是详细解释一切。希望这对某人有用。

回答得既好又翔实。包括示例和参考链接。将尽快给予悬赏。谢谢。这是托拉迪安语而不是托拉迪安语:)