使用 Matrix4f 围绕多个轴进行框旋转
Box rotation around multiple axises using Matrix4f
问题变了一点,我想出了绕单轴旋转的方法
我想使用一个角度围绕 Y 轴旋转一个盒子。
该框有一个大小和一个 Vector3f 来表示旋转。
为了正确旋转盒子,我所做的是旋转原点位置,然后旋转原点位置加上大小,并使用这两个参考来渲染盒子。
然而,这种旋转无法正常工作并导致渲染瑕疵。
这是我旋转位置的代码:
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));
Billboards 是计算机图形学的一个非常常见的应用程序(我相信你已经注意到了,因为你在问这个问题!)
最终我认为你把问题复杂化了,基于:
as in rotate the origin position then rotate the origin position plus the size..
对于计算机图形,最常见的变换是缩放、平移和旋转,您按顺序执行这些操作以获得所需的效果(传统上先缩放,然后绕原点旋转,然后平移顶点的位置) .
此外,您将使用三个主要矩阵来渲染 3d 模型:世界矩阵、视图矩阵和投影矩阵。我相信你对从 Model Space 转换到 World Space.
有误解
Graphics TRS and Matrix info。如果您有概念上的问题,或者这个答案不够充分,我强烈建议您查看此 link。我还没有找到更好的资源来解释计算机图形学的基础知识。
所以现在,您有三个角度(以度为单位,在 Vector3 中)对应于广告牌和相机的 X、Y 和 Z 坐标 spaces 中的角度差.有了这些信息,我们首先将所有矩阵转换收集到一个地方来生成视图矩阵。
我假设您已经有了平移矩阵和缩放矩阵,并且它们都有效。这意味着我们只需要生成我们的旋转矩阵,然后用缩放矩阵变换那个矩阵,然后用我们的平移矩阵变换那个矩阵。
X 旋转矩阵
Y 旋转矩阵
Z 旋转矩阵
(以上图片取自 CodingLabs link)
所以你会生成这三个矩阵,使用你之前计算的X,Y,Z角度,然后将它们变换合并成一个矩阵,变换that通过缩放矩阵转换矩阵,然后通过平移矩阵转换that矩阵。现在你有了很棒的矩阵,当你将一个顶点乘以它时,会将该顶点转换为所需的大小、旋转和位置。
所以你用这个生成的矩阵变换每个顶点。
然后,你应该完成了!使用这些技术有望大大简化您的代码,并让您走上正确的道路:)
那么现在来一些代码怎么样?
//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 文档 Here
中获取了方法
这是正在发生的事情的图像(同样,取自编码实验室):
(高级信息:Quaternions。这些是在 3d 中定向模型的非常酷的方法 space,但是我对它们的理解程度还不够,无法解释它给别人,我也相信你的问题更根本)
您可以毫不费力地生成矩阵。 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 设置为您的盒子在世界中的位置,
你的视图向量到标准化(相机位置 - 框位置),你的向上直接来自你的相机,左边是通过标准化叉积计算的。在导出左向量(通过另一个叉积)后,重建向上向量也是一种很好的做法。仅此而已。
我的解决方案旨在为您节省一些编码时间,而不是详细解释所有内容。希望对某人有用。
问题变了一点,我想出了绕单轴旋转的方法
我想使用一个角度围绕 Y 轴旋转一个盒子。 该框有一个大小和一个 Vector3f 来表示旋转。
为了正确旋转盒子,我所做的是旋转原点位置,然后旋转原点位置加上大小,并使用这两个参考来渲染盒子。
然而,这种旋转无法正常工作并导致渲染瑕疵。
这是我旋转位置的代码:
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));
Billboards 是计算机图形学的一个非常常见的应用程序(我相信你已经注意到了,因为你在问这个问题!)
最终我认为你把问题复杂化了,基于:
as in rotate the origin position then rotate the origin position plus the size..
对于计算机图形,最常见的变换是缩放、平移和旋转,您按顺序执行这些操作以获得所需的效果(传统上先缩放,然后绕原点旋转,然后平移顶点的位置) .
此外,您将使用三个主要矩阵来渲染 3d 模型:世界矩阵、视图矩阵和投影矩阵。我相信你对从 Model Space 转换到 World Space.
有误解Graphics TRS and Matrix info。如果您有概念上的问题,或者这个答案不够充分,我强烈建议您查看此 link。我还没有找到更好的资源来解释计算机图形学的基础知识。
所以现在,您有三个角度(以度为单位,在 Vector3 中)对应于广告牌和相机的 X、Y 和 Z 坐标 spaces 中的角度差.有了这些信息,我们首先将所有矩阵转换收集到一个地方来生成视图矩阵。
我假设您已经有了平移矩阵和缩放矩阵,并且它们都有效。这意味着我们只需要生成我们的旋转矩阵,然后用缩放矩阵变换那个矩阵,然后用我们的平移矩阵变换那个矩阵。
(以上图片取自 CodingLabs link)
所以你会生成这三个矩阵,使用你之前计算的X,Y,Z角度,然后将它们变换合并成一个矩阵,变换that通过缩放矩阵转换矩阵,然后通过平移矩阵转换that矩阵。现在你有了很棒的矩阵,当你将一个顶点乘以它时,会将该顶点转换为所需的大小、旋转和位置。
所以你用这个生成的矩阵变换每个顶点。
然后,你应该完成了!使用这些技术有望大大简化您的代码,并让您走上正确的道路:)
那么现在来一些代码怎么样?
//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 文档 Here
中获取了方法这是正在发生的事情的图像(同样,取自编码实验室):
(高级信息:Quaternions。这些是在 3d 中定向模型的非常酷的方法 space,但是我对它们的理解程度还不够,无法解释它给别人,我也相信你的问题更根本)
您可以毫不费力地生成矩阵。 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 设置为您的盒子在世界中的位置, 你的视图向量到标准化(相机位置 - 框位置),你的向上直接来自你的相机,左边是通过标准化叉积计算的。在导出左向量(通过另一个叉积)后,重建向上向量也是一种很好的做法。仅此而已。
我的解决方案旨在为您节省一些编码时间,而不是详细解释所有内容。希望对某人有用。