沿表面法线定向对象

时间:2017-03-27 23:26:06

标签: opengl rotation orientation transformation normals

当用户点击表面时,我想在此位置放置一个物体,并使其垂直于表面法线。

用户执行单击后,我从缓冲区中读取三个相邻像素的深度,从屏幕坐标到对象空间取消投影像素,然后从对象空间中的这些点计算曲面法线:

glReadPixels(mouseX, mouseY, ..., &depthCenter);
pointCenter = gluUnProject(mouseX, mouseY, depthCenter, ...);

glReadPixels(mouseX, mouseY - 1, ..., &depthUp);
pointUp = gluUnProject(mouseX, mouseY - 1, depthUp, ...);

glReadPixels(mouseX - 1, mouseY, ..., &depthLeft);
pointLeft = gluUnProject(mouseX - 1, mouseY, depthLeft, ...);

centerUpVec = norm( pointCenter - pointUp );
centerLeftVec = norm( pointCenter - pointLeft );
normalVec = norm( centerUpVec.cross(centerLeftVec) );

我知道从三个像素计算法线是有问题的(例如在边缘或三个点的深度差异很大),但是对于我在平面上的初步测试,这必须足够。

最后,为了沿着计算的法线向量定向对象,我从法线向量和向上向量创建一个旋转矩阵:

upVec = vec(0.0f, 1.0f, 0.0f);
xAxis = norm( upVec.cross(normalVec) );
yAxis = norm( normalVec.cross(xAxis) );

// set orientation of model matrix
modelMat(0,0) = xAxis(0);
modelMat(1,0) = yAxis(0);
modelMat(2,0) = normalVec(0);

modelMat(0,1) = xAxis(1);
modelMat(1,1) = yAxis(1);
modelMat(2,1) = normalVec(1);

modelMat(0,2) = xAxis(2);
modelMat(1,2) = yAxis(2);
modelMat(2,2) = normalVec(2);

// set position of model matrix by using the previously computed center-point
modelMat(0,3) = pointCenter(0);
modelMat(1,3) = pointCenter(1);
modelMat(2,3) = pointCenter(2);

出于测试目的,我会在每次点击后将物体放在平面上。在大多数情况下,当我的相机朝下向上矢量时,这种方法效果很好。

然而,一旦我旋转相机,放置的物体就是任意定向的,我无法弄清楚原因!

1 个答案:

答案 0 :(得分:0)

好的,我刚在代码中发现了一个与实际问题无关的小愚蠢错误。因此,上述问题中陈述的方法是正确的。

为了避免一些陷阱,当然可以使用数学库,例如Eigen,以计算向上矢量和表面法线之间的旋转:

upVec = Eigen::Vector3f(0.0f, 1.0f, 0.0f);
Eigen::Quaternion<float> rotationQuat;
rotationQuat.setFromTwoVectors(upVec, normalVec);