【发布时间】:2017-03-27 23:26:06
【问题描述】:
当用户点击一个表面时,我想在这个位置放置一个对象并使其垂直于表面法线。
用户执行点击后,我从缓冲区读取三个相邻像素的深度,将像素从屏幕坐标解投影到对象空间,然后从对象空间中的这些点计算表面法线:
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);
出于测试目的,我在每次单击后将对象放置在平坦的表面上。在大多数情况下,当我的相机朝上矢量向下时,这很有效。
但是,一旦我旋转我的相机,放置的对象就会任意定向,我不知道为什么!
【问题讨论】:
-
您的
xAxis和yAxis是相等的。您应该使用xAxis来计算yAxis。喜欢这个yAxis = norm( upVec.cross(xAxis) );。此外,如果normalVec和upVec共线(如果可能的话),最好使用另一个upVec。 -
而不是使用 3 个像素来计算法线,只需确定单击了哪个面/多边形(使用
glSelectBuffer等),并使用该面的法线。 -
@MichaelNastenko 这只是一个错字,谢谢指出!
-
@1201ProgramAlarm 如前所述,我知道有更好的方法来计算法线,但这应该足以在平面上进行测试,直到一切正常......
标签: opengl rotation orientation transformation normals