3D点旋转算法
3D point rotation algorithm
我目前正在从事一个涉及 3D 点旋转的 JavaScript 项目。使用简单的三角函数,我绘制了我自己的 3D 点旋转算法,但我必须处理大量数据(+300 000 点)并且我的函数大大减慢了运行时间(FPS 速率从 60 下降到 12)。
I'm looking for another 3D point rotation ALGORITHM which...
- rotates points around origin by X, Y and Z axes' angles (PITCH, YAW and ROLL)
- has a quite good efficiency (don't worry about this too much, it will always be faster than mine)
- is written in JavaScript, C-like code or pseudo-code
任何帮助将不胜感激:)
上下文:3D点云渲染器(我想让每个点都旋转)
来自维基百科:
如果你将你的点乘以这些矩阵中的每一个,它们将旋转你想要的量。
例如,如果我想将点 [1, 0, 0]
绕 z 轴(在 xy 平面中)旋转 90°,则 sin(90) = 1
和 cos(90) = 0
将得到:
| 0 -1 0 | |1| |0|
| 1 0 0 | * |0| = |1|
| 0 0 1 | |0| |0|
旋转向量可以描述为旋转矩阵与该向量的乘积。 German Wikipedia page on pitch, roll and yaw 描述了给定欧拉旋转角度的旋转矩阵。
根据这些信息,所有具有相同角度的点的旋转可以写成JavaScript函数,其中points数组是全局的:
function rotate(pitch, roll, yaw) {
var cosa = Math.cos(yaw);
var sina = Math.sin(yaw);
var cosb = Math.cos(pitch);
var sinb = Math.sin(pitch);
var cosc = Math.cos(roll);
var sinc = Math.sin(roll);
var Axx = cosa*cosb;
var Axy = cosa*sinb*sinc - sina*cosc;
var Axz = cosa*sinb*cosc + sina*sinc;
var Ayx = sina*cosb;
var Ayy = sina*sinb*sinc + cosa*cosc;
var Ayz = sina*sinb*cosc - cosa*sinc;
var Azx = -sinb;
var Azy = cosb*sinc;
var Azz = cosb*cosc;
for (var i = 0; i < points.length; i++) {
var px = points[i].x;
var py = points[i].y;
var pz = points[i].z;
points[i].x = Axx*px + Axy*py + Axz*pz;
points[i].y = Ayx*px + Ayy*py + Ayz*pz;
points[i].z = Azx*px + Azy*py + Azz*pz;
}
}
其中大部分是按照文章中的描述设置旋转矩阵。循环中的最后三行是矩阵乘法。你已经强调不想进入矩阵,但这并不可怕,是吗?迟早你会遇到更多的矩阵,你应该准备好处理它们。你需要的东西——主要是乘法——很简单。您的要求不需要更复杂的东西,例如求逆矩阵。
无论如何,这对于 300,000 点来说执行得相当快。我能够旋转那个大小的点云,并在大约 10 毫秒内将其渲染到 1000px × 1000px canvas。
我目前正在从事一个涉及 3D 点旋转的 JavaScript 项目。使用简单的三角函数,我绘制了我自己的 3D 点旋转算法,但我必须处理大量数据(+300 000 点)并且我的函数大大减慢了运行时间(FPS 速率从 60 下降到 12)。
I'm looking for another 3D point rotation ALGORITHM which...
- rotates points around origin by X, Y and Z axes' angles (PITCH, YAW and ROLL)
- has a quite good efficiency (don't worry about this too much, it will always be faster than mine)
- is written in JavaScript, C-like code or pseudo-code
任何帮助将不胜感激:)
上下文:3D点云渲染器(我想让每个点都旋转)
来自维基百科:
如果你将你的点乘以这些矩阵中的每一个,它们将旋转你想要的量。
例如,如果我想将点 [1, 0, 0]
绕 z 轴(在 xy 平面中)旋转 90°,则 sin(90) = 1
和 cos(90) = 0
将得到:
| 0 -1 0 | |1| |0|
| 1 0 0 | * |0| = |1|
| 0 0 1 | |0| |0|
旋转向量可以描述为旋转矩阵与该向量的乘积。 German Wikipedia page on pitch, roll and yaw 描述了给定欧拉旋转角度的旋转矩阵。
根据这些信息,所有具有相同角度的点的旋转可以写成JavaScript函数,其中points数组是全局的:
function rotate(pitch, roll, yaw) {
var cosa = Math.cos(yaw);
var sina = Math.sin(yaw);
var cosb = Math.cos(pitch);
var sinb = Math.sin(pitch);
var cosc = Math.cos(roll);
var sinc = Math.sin(roll);
var Axx = cosa*cosb;
var Axy = cosa*sinb*sinc - sina*cosc;
var Axz = cosa*sinb*cosc + sina*sinc;
var Ayx = sina*cosb;
var Ayy = sina*sinb*sinc + cosa*cosc;
var Ayz = sina*sinb*cosc - cosa*sinc;
var Azx = -sinb;
var Azy = cosb*sinc;
var Azz = cosb*cosc;
for (var i = 0; i < points.length; i++) {
var px = points[i].x;
var py = points[i].y;
var pz = points[i].z;
points[i].x = Axx*px + Axy*py + Axz*pz;
points[i].y = Ayx*px + Ayy*py + Ayz*pz;
points[i].z = Azx*px + Azy*py + Azz*pz;
}
}
其中大部分是按照文章中的描述设置旋转矩阵。循环中的最后三行是矩阵乘法。你已经强调不想进入矩阵,但这并不可怕,是吗?迟早你会遇到更多的矩阵,你应该准备好处理它们。你需要的东西——主要是乘法——很简单。您的要求不需要更复杂的东西,例如求逆矩阵。
无论如何,这对于 300,000 点来说执行得相当快。我能够旋转那个大小的点云,并在大约 10 毫秒内将其渲染到 1000px × 1000px canvas。