简体   繁体   English

沿表面法线定向对象

[英]Orient object along surface normal

When the user clicks on a surface I would like place an object at this position and orient it perpendicular to the surface normal. 当用户单击表面时,我想将一个对象放置在此位置并将其垂直于表面法线定向。

After the user performs a click, I read the depth of three neighboring pixels from the buffer, unproject the pixels from screen coordinates to object space and then compute the surface normal from these points in object space: 用户单击后,我从缓冲区读取了三个相邻像素的深度,将像素从屏幕坐标投影到对象空间,然后从对象空间中的这些点计算表面法线:

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) );

I know that computing the normal just from three pixels is problematic (eg at edges or if the three points have vastly different depth), but for my initial test on a flat surface this must suffice. 我知道仅从三个像素计算法线是有问题的(例如,在边缘或三个点的深度有很大不同),但是对于我在平坦表面上的初始测试来说,这足够了。

Finally, in order to orient the object along the computed normal vector I create a rotation matrix from the normal and the up vector: 最后,为了使对象沿着计算出的法线向量定向,我从法线向量和向上向量创建旋转矩阵:

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);

For testing purposes I'm placing an objects on a flat surface after each click. 出于测试目的,每次单击后,我将一个物体放置在一个平面上。 This works well in most cases when my camera is facing downwards the up vector. 在大多数情况下,当我的相机朝下向上矢量时,此方法效果很好。

However, once I rotate my camera the placed objects are oriented arbitrarily and I can't figure out why! 但是,一旦旋转相机,放置的对象便会任意定向,我不知道为什么!

Ok, I just found a small, stupid bug in my code that was unrelated to the actual problem. 好的,我只是在代码中发现了一个与实际问题无关的小愚蠢错误。 Therefore, the approach stated in the question above is working correctly. 因此,上述问题中所述的方法可以正常工作。

In order to avoid some pitfalls, one could of course just use a math library, such as Eigen, in order to compute the rotation between the up vector and the surface normal: 为了避免某些陷阱,当然可以使用数学库(例如Eigen)来计算向上矢量和表面法线之间的旋转:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM