射线 - 三角形交叉的射线变换

时间:2010-10-18 23:17:47

标签: math opengl matrix 3d raytracing

在openGL中,我有一个3D模型,我正在使用“Fast,Minimum Storage Ray / Triangle Intersection”(http://jgt.akpeters.com/papers/MollerTrumbore97/)文章中解释的代码执行光线 - 三角形交叉。

使用以下代码将我的光标位置取消投影到世界空间:

bool SCamera::unproject(Vector3 input, Vector3 & output){

  GLint viewport[4]; 
  glGetIntegerv(GL_VIEWPORT,viewport); //Grab screen info

  float x = input.mX; 
  float y = input.mY;
  float z = input.mZ;

  Matrix4 P, Mv, res;

  P = getProjection();
  Mv = getCameraTransform();

  Vector3 N; //Cursor point translated to having 0,0 at screen center
  N.mX = ((x-viewport[0]) / viewport[2])*2 - 1;
  N.mY = ((y-viewport[1]) / viewport[3])*2 - 1;
  N.mZ = z*2-1;

  res = P * Mv; //Multiply P * Mv to get transform
  Vector3 w = res.inverse() * N; //Apply transform to N.

  output.mX = w[0];
  output.mY = w[1];
  output.mZ = w[2];
  return true;
}

之后,我通过以下方式形成一条光线:

unproject(Vector3(xClick, yClick,0),resultUnproject)
ray.origin = cameraPosition;
ray.direction = resultUnproject - ray.origin;
ray.direction.normalize();

现在,最后我试图通过三角形代码(上面链接)运行此光线,但我似乎无法正确转换它。我目前的尝试如下:

Matrix4 mview, T;
mview = getModelview();
T = mview.inverse();
ray.origin = T*ray.origin;
ray.direction = T*ray.direction;
ray.direction.normalize();

出于某种原因,这不起作用。我的光线错了吗?或者改错了?

4 个答案:

答案 0 :(得分:3)

一种方法可能是:

获取光线原点,然后在世界空间中光线方向的单位距离处计算出一个点。然后,转换到两个点 - 即乘以变换矩阵的逆。然后,您可以根据两个平移点之间的差异确定新的光线方向。检查此方向是否与原稿不同将很快告诉您是否缺少步骤。

答案 1 :(得分:3)

我的解决办法就是按照sje397的建议去做,但只是将结果用作新的光线。

所以在我的项目(XNA)中,给定ray未从光标投影:

rayTransform = Matrix.Invert(model_transform);

//Transform ray (or more accurately its defining components into a new ray)
Vector3 v1 = Vector3.Transform(ray.Position, rayTransform);
Vector3 v2 = Vector3.Transform((ray.Position + ray.Direction), rayTransform);
transformedray = new Ray(v1, v2 - v1);

model_transform这里生成的方式与着色器的变换相同(即不交换世界/本地乘法或任何东西)

这在我的项目中运行良好,目标是以各种方式旋转,转换和缩放拾取目标。

另外,您可能会觉得这有点不合适但是如果您仍然遇到问题,您是否确定要取消投影光标并生成拾取光线的代码是正确的?我猜想如果你的三角形拾取代码有效,它就会让我看起来就像它以一种“四舍五入”的方式获得光线。

在我的项目中,我拿了两个点,一个在'视口'平面'上,所以Vector3(cursorx,cursory,0)再一次,但是在Z轴Vector3(cursorx,cursory,1)上前进。取消投影这两个点,第一个的结果是你的起源,差异是你的方向。

祝你好运!

答案 2 :(得分:0)

所以我终于有了这个工作,虽然我对如何不满意。在我的例子中,单个模型旋转在渲染之前被应用为变换,因此我最终必须通过模型视图矩阵变换目标三角形。

我上面尝试做的是通过在物体周围移动光线的原点来计算可用于相同目的的光线,这样就好像物体已被旋转一样。不幸的是,我无法完全正确地计算数学。

最终结果表示每个三角形一个变换,而不是每个光线一个变换。幸运的是,它似乎没有那么糟糕的性能,因为我只是用它来挑选。

答案 3 :(得分:0)

如果您有一些光线(已经变换到世界空间)并且您想要检查它是否与对象/三角形相交,则需要将其乘以对象的反转矩阵。这是一些伪代码:

NewRayPosition = Vector3.Transform(OldRay.Position, Matrix.Invert(Transformation);
NewRayDirection = Vector3.Transform(OldRay.Direction, Matrix.Invert(Rotation*Scale));
NewRayDirection.Normalize();

通过平移,缩放和旋转乘以光线位置,但仅通过缩放和旋转方向。由于性能原因,按照您的方式进行操作是不可接受的。 更多信息: http://www.cl.cam.ac.uk/teaching/1999/AGraphHCI/SMAG/node2.html#SECTION00024100000000000000

相关问题