正如其他评论所暗示的那样,您很可能对投影和测角学感到困惑。还有一种更安全的方法,无需使用矢量数学(线性代数)进行测角。
-
创建变换矩阵m0
表示与第一个三角形对齐的平面t0
通过对齐我的意思是三角形的边之一应该位于平面基向量之一中。这很简单,您只需将一个基向量设置为相关边缘,将原点设置为其点之一,然后利用叉积来获取剩余的向量。
所以如果我们的三角形有点p0,p1,p2
我们的基向量是x,y,z
有起源o
then:
x = p1-p0; x /= |x|;
y = p2-p0;
z = cross(x,y); z /= |z|;
y = cross(z,x); y /= |y|;
o = p0
所以只需将它们输入变换矩阵(请参阅答案底部的链接)
-
创建变换矩阵m1
表示与第二个三角形对齐的平面t1
它等同于#1
-
计算最终变换矩阵m
转换t1
to t0
这很简单:
m = Inverse(m1)*m0
现在任意一点t1
可以对齐到t0
简单地通过乘法m
矩阵按点。不要忘记使用齐次坐标,这样point(x,y,z,1)
这里小C++/OpenGL例子:
//---------------------------------------------------------------------------
double t0[3][3]= // 1st triangle
{
-0.5,-0.5,-1.2,
+0.5,-0.5,-0.8,
0.0,+0.5,-1.0,
};
double t1[3][3]= // 2nd triangle
{
+0.5,-0.6,-2.1,
+1.5,-0.5,-2.3,
+1.2,+0.3,-2.2,
};
double arot=0.0; // animation angle
//---------------------------------------------------------------------------
void gl_draw() // main rendering code
{
int i;
double m0[16],m1[16],m[16],x[3],y[3],z[3],t2[3][3];
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDisable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslated(0.0,0.0,-10.0);
glRotatef(arot,0.0,1.0,0.0);
// render original triangles
glBegin(GL_TRIANGLES);
glColor3f(1.0,0.0,0.0); for (i=0;i<3;i++) glVertex3dv(t0[i]);
glColor3f(0.0,0.0,1.0); for (i=0;i<3;i++) glVertex3dv(t1[i]);
glEnd();
// x,y,z = t0 plane basis vectors
vector_sub(x,t0[1],t0[0]); // x is fisrt edge
vector_one(x,x); // normalized
vector_sub(y,t0[2],t0[0]); // y is last edge
vector_mul(z,x,y); // z = cross(x,y) ... perpendicular vector to x,y
vector_one(z,z);
vector_mul(y,z,x); // y = cross(z,x) ... perpendicular vector to z,x
vector_one(y,y);
// m0 = transform matrix representing t0 plane
m0[ 3]=0.0; for (i=0;i<3;i++) m0[ 0+i]=x[i];
m0[ 7]=0.0; for (i=0;i<3;i++) m0[ 4+i]=y[i];
m0[11]=0.0; for (i=0;i<3;i++) m0[ 8+i]=z[i];
m0[15]=1.0; for (i=0;i<3;i++) m0[12+i]=t0[0][i];
// x,y,z = t1 plane basis vectors
vector_sub(x,t1[1],t1[0]); // x is fisrt edge
vector_one(x,x); // normalized
vector_sub(y,t1[2],t1[0]); // y is last edge
vector_mul(z,x,y); // z = cross(x,y) ... perpendicular vector to x,y
vector_one(z,z);
vector_mul(y,z,x); // y = cross(z,x) ... perpendicular vector to z,x
vector_one(y,y);
// m1 = transform matrix representing t1 plane
m1[ 3]=0.0; for (i=0;i<3;i++) m1[ 0+i]=x[i];
m1[ 7]=0.0; for (i=0;i<3;i++) m1[ 4+i]=y[i];
m1[11]=0.0; for (i=0;i<3;i++) m1[ 8+i]=z[i];
m1[15]=1.0; for (i=0;i<3;i++) m1[12+i]=t1[0][i];
// m = transform t1 -> t0 = Inverse(m1)*m0
matrix_inv(m,m1);
matrix_mul(m,m,m0);
// t2 = transformed t1
for (i=0;i<3;i++) matrix_mul_vector(t2[i],m,t1[i]);
// render transformed triangle
glLineWidth(2.0);
glBegin(GL_LINE_LOOP);
glColor3f(0.0,1.0,0.0); for (i=0;i<3;i++) glVertex3dv(t2[i]);
glLineWidth(1.0);
glEnd();
glFlush();
SwapBuffers(hdc);
}
//---------------------------------------------------------------------------
我使用了自己的矩阵和向量数学,希望评论足够,如果没有看到的话:
有关矩阵的信息,您也可以找到那里使用的数学的来源和方程。这里是我的测试用例的预览:
红色在哪里t0
蓝色三角形是t1
三角形和绿色是m*t1
变换后的三角形。正如您所看到的,根本不需要测角/欧拉角。我旋转这些东西arot
只是为了目视检查绿色三角形是否真的与蓝色对齐,以证明我没有犯一个愚蠢的错误。
现在还不清楚您到底想要如何对齐,因此,例如,如果您想要最大覆盖范围或尝试所有 3 种组合并记住最佳组合,或者对齐到两个三角形的最近或最大边缘等...