1

在 openGL 中,我有一个 3D 模型,我正在使用论文“快速、最小存储射线/三角形交点”(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

4 回答 4

3

一种方法可能是:

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

于 2010-10-18T23:32:00.090 回答
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)。取消投影这两个点,第一个的结果是你的原点,不同的是你的方向。

祝你好运!

于 2011-02-12T18:27:13.020 回答
0

所以我终于得到了这个工作,虽然我对如何工作不满意。在我的情况下,单个模型旋转在渲染之前被应用为变换,所以我最终不得不通过模型视图矩阵变换目标三角形。

我在上面尝试做的是计算一条可以达到相同目的的光线,方法是围绕对象移动光线的原点,就好像对象已经旋转了一样。不幸的是,我无法完全正确地计算出数学。

最终结果意味着每个三角形一次变换,而不是每条射线一次。幸运的是,它似乎并没有对性能造成那么糟糕的影响,因为我只是用它来挑选。

于 2010-10-22T13:02:31.010 回答
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

于 2013-06-14T15:19:52.000 回答