如果我错了,请纠正我,但是......
给定任意源平面的法线,以及应用所需旋转后平面的法线:
Vector3F sourceNormal = (x, y, z).normalize()
Vector3F desiredNormal = (0, 0, 1).normalize()
1)我们可以通过两个法线的交叉积来找到“旋转轴”
Vector3F rotationAxis = Vector3F.cross(sourceNormal, desiredNormal).normalize()
2)我们可以通过两个法线的点积的弧余弦找到“旋转角”。
// Thanks nico - it was there in my project source, but it was omitted here.
float theta = Math.acos(Vector3F.dot(sourceNormal, desiredNormal))
3)我们可以将旋转应用于一组点,以便将源平面定向到我们想要的平面。
float[] rotationMatrix = new float[16];
// X component
rotationMatrix[5] = rotationMatrix[10] = (float)Math.cos(theta);
rotationMatrix[9] = (float)Math.sin(theta);
rotationMatrix[6] = -rotationMatrix[9];
// Y component
rotationMatrix[0] = rotationMatrix[10] = (float)Math.cos(theta);
rotationMatrix[2] = (float)Math.sin(theta);
rotationMatrix[8] = -rotationMatrix[2];
// Z component
rotationMatrix[0] = rotationMatrix[5] = (float)Math.cos(theta);
rotationMatrix[1] = (float)Math.sin(theta);
rotationMatrix[4] = -rotationMatrix[1];
for(Point3F point : polygon)
{
float x = pt.getX();
float y = pt.getY();
float z = pt.getZ();
float[] xs = new float[3];
float[] ys = new float[3];
float[] zs = new float[3];
for(int j = 0; j < 3; ++j)
{
xs[j] = rotationMatrix[j] * x;
ys[j] = rotationMatrix[j + 4] * y;
zs[j] = rotationMatrix[j + 8] * z;
}
x = 0; y = 0; z = 0;
for(int j = 0; j < 3; ++j)
{
x += xs[j];
y += ys[j];
z += zs[j];
}
pt.set(x, y, z);
}
我的输出不正确。
点数:
(-56.00, 72.01, 48.02)
(-48.00, 72.01, 48.02)
(-48.00, 86.01, 24.02)
(-56.00, 86.01, 24.02)
Out Points:
(-124.960010, -88.105451, 24.185812)
(-107.108590, -88.105451, 24.185812)
(-107.108590, -105.237051, 12.0929052)
(-124.960010, -105.237051, 12.0929052)
如果我不得不猜测,我会说我正在不正确地应用旋转点...也许我已经错误地解释了本文中的旋转矩阵(http://en.wikipedia.org/wiki/Rotation_matrix)?
感谢您的任何意见。
...假设这是设置旋转矩阵的正确方法,输出仍然不正确:
Vector3F axis = Vector3F.cross(sourceNormal, desiredNormal).normalize();
float angle = (float) Math.acos(p.normal.dot(new Vector3F(0, 0, 1)));
float s = (float)Math.sin(angle);
float c = (float)Math.cos(angle);
float x = axis.getX(), y = axis.getY(), z = axis.getZ();
float[] matrix = new float[16];
matrix[0] = x * x * (1 - c) + c;
matrix[1] = x * y * (1 - c) - (z * s);
matrix[2] = x * z * (1 - c) + (y * s);
matrix[4] = y * x * (1 - c) + (z * s);
matrix[5] = y * y * (1 - c) + c;
matrix[6] = y * z * (1 - c) - (x * s);
matrix[8] = x * z * (1 - c) - (y * s);
matrix[9] = y * z * (1 - c) + (x * s);
matrix[10] = z * z * (1 - c) + c;
float nx = x * matrix[0] + y * matrix[1] + z * matrix[2];
float ny = x * matrix[4] + y * matrix[5] + z * matrix[6];
float nz = x * matrix[8] + y * matrix[9] + z * matrix[10];
In: (-56.00, 56.01, -16.02)
In: (-48.00, 56.01, -16.02)
In: (-48.00, 72.01, -8.02)
In: (-56.00, 72.01, -8.02)
Out: (-51.270340, 46.887921, -25.5108342)
Out: (-43.9460070, 46.887921, -25.5108342)
Out: (-43.9460070, 62.798761, -21.5554182)
Out: (-51.270340, 62.798761, -21.5554182)
答案 0 :(得分:1)
您的旋转矩阵错误。
旋转需要根据您链接到的维基百科文章的第10部分中的公式进行组合(“轴和角度的旋转矩阵”)。
此矩阵的简化版也可以在glRotate
函数的手册页中找到。
注意:除非您反复重复轮换,否则无需再次acos(dotp)
取cos
和sin
。将点积直接用作cos(theta)
,并使用sin(theta)^2 = 1 - cos(theta)^2
关系计算sin(theta)
。
答案 1 :(得分:0)
最终,有很多问题。 Alnitak解决了绝大多数问题,我刚刚找到了最后一个。
简而言之,以下是错误的:
1)矩阵创建
2)矩阵乘法
3)浮点截断
即使它可能是一个hacky解决方案,它对我的目的也没关系。工作片段如下。
Vector3F axis = new Vector3F(p.normal);
// Seems to work when adding precision...but NOT with (0, 0, 1)
Vector3F target = new Vector3F(0.000000000000000001f, 0.000000000000001f, 1.0f);
axis.cross(target);
axis.normalize();
float angle = (float) Math.acos(p.normal.dot(new Vector3F(0, 0, 1)));
float s = (float) Math.sin(angle);
float c = (float) Math.cos(angle);
float x = axis.getX(), y = axis.getY(), z = axis.getZ();
float[] matrix = new float[16];
matrix[0] = x * x * (1 - c) + c;
matrix[1] = x * y * (1 - c) - (z * s);
matrix[2] = x * z * (1 - c) + (y * s);
matrix[4] = y * x * (1 - c) + (z * s);
matrix[5] = y * y * (1 - c) + c;
matrix[6] = y * z * (1 - c) - (x * s);
matrix[8] = x * z * (1 - c) - (y * s);
matrix[9] = y * z * (1 - c) + (x * s);
matrix[10] = z * z * (1 - c) + c;
float nx = x * matrix[0] + y * matrix[1] + z * matrix[2];
float ny = x * matrix[4] + y * matrix[5] + z * matrix[6];
float nz = x * matrix[8] + y * matrix[9] + z * matrix[10];
// triangulate (now 2D) polygon
// Rotate the points back
angle = -angle;
s = (float) Math.sin(angle);
c = (float) Math.cos(angle);
matrix[0] = x * x * (1 - c) + c;
matrix[1] = x * y * (1 - c) - (z * s);
matrix[2] = x * z * (1 - c) + (y * s);
matrix[4] = y * x * (1 - c) + (z * s);
matrix[5] = y * y * (1 - c) + c;
matrix[6] = y * z * (1 - c) - (x * s);
matrix[8] = x * z * (1 - c) - (y * s);
matrix[9] = y * z * (1 - c) + (x * s);
matrix[10] = z * z * (1 - c) + c;
nx = x * matrix[0] + y * matrix[1] + z * matrix[2];
ny = x * matrix[4] + y * matrix[5] + z * matrix[6];
nz = x * matrix[8] + y * matrix[9] + z * matrix[10];
// All's well that ends well