射线与三角形相交的射线变换

发布于 2024-09-28 04:54:46 字数 1387 浏览 9 评论 0原文

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

由于某种原因,这不起作用。我的光线形成错误吗?还是改造错了?

In openGL, I have a 3D model I'm performing a ray-triangle intersection on, using the code explained in the paper "Fast, Minimum Storage Ray/Triangle Intersection" ( http://jgt.akpeters.com/papers/MollerTrumbore97/ ).

My cursor position is unprojected into world space using the following code:

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

After that, I form a ray by doing the following:

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

Now, finally I'm trying to run this ray through the triangle code (linked above), but I can't seem to transform it right. My current attempt is as follows:

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

For some reason, this doesn't work. Am I forming my ray wrong? Or transforming it wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

梦罢 2024-10-05 04:54:46

一种方法可能是:

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

One method might be:

Take your ray origin, and work out a point at a unit distance in the direction of the ray in world space. Then, do your transformation to both points - i.e. multiply by the inverse of the transformation matrix. You can then determine the new ray direction from the difference between the two translated points. Checking if this direction is different to the original will quickly tell you whether you are missing a step.

万水千山粽是情ミ 2024-10-05 04:54:46

我的解决方案是按照 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 这里的生成方式与着色器的变换相同(即没有交换 World/局部乘法或任何东西)

这在我的项目中工作得很好,拾取的目标以各种方式旋转、转换和缩放。

另外,您可能会发现这有点不礼貌,但如果您仍然遇到问题,您确定取消投影光标并生成拾取光线的代码工作正常吗?我想如果你的三角形拾取代码有效的话,它就必须是这样,在我看来,它就像以“绕圈”的方式获取光线。

在我的项目中,我取了两个点,一个在视口“平面”上,所以再次 Vector3(cursorx,cursory,0) 但在 Z 轴上前进Vector3(cursorx,cursory, 1)。将这两点都投影出来,第一点的结果就是你的原点,差异就是你的方向。

祝你好运!

My solution to this was to do what sje397 suggested but just use the result as your new ray.

So in my project (which is XNA), given ray unprojected from the cursor:

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 here is generated the same way as the transform for the shader (i.e. no swapping World/Local multiplications or anything)

This works fine in my project with the target of the picking being rotated, transformed and scaled in all sorts of ways.

Also, you may find this a little impertient but if you are still having trouble are you sure the code to unproject the cursor and generate the picking ray works right? I would guess it would have to if your triangle picking code works, its just it looks to me like its getting the ray in a 'round about' way.

In my project I take two points, one 'on' the viewport 'plane' so Vector3(cursorx,cursory,0) this again but advanced on the Z axis Vector3(cursorx,cursory,1). Unproject both these points, the result of the first is your origin and the difference is your direction.

Good luck!

小姐丶请自重 2024-10-05 04:54:46

所以我终于开始工作了,尽管我对如何工作并不满意。在我的例子中,单个模型旋转在渲染之前作为变换应用,所以我最终不得不通过模型视图矩阵来变换目标三角形。

上面我试图做的是计算一条具有相同目的的光线,方法是围绕物体移动光线的原点,就像物体被旋转一样。不幸的是,我无法完全正确地计算出数学。

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

So I finally got this working, though I'm not satisfied with how. In my case individual model rotation is applied as a transform before rendering, so I ended up having to transformed the target triangle by the modelview matrix.

What I was trying to do above was compute a ray that would serve the same purpose, by moving the ray's origin around the object so it's as if the object had been rotated. Unfortunately, I couldn't quite get the math right.

The end result means one transform per triangle, instead of one per ray. Luckily enough it doesn't seem to be that bad of a performance hit, as I'm only using this for picking.

〗斷ホ乔殘χμё〖 2024-10-05 04:54:46

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

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

If you have some ray (already transformed to world space) and you want to check if it intersects an object/triangle, you need to multiply it by object's inverted matrices. Here's some pseudocode:

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

Multiply ray position by Translation, Scale and Rotation, but direction only by Scale and Rotation. Doing it the way you did it is unacceptable because of the performance reason.
More here:
http://www.cl.cam.ac.uk/teaching/1999/AGraphHCI/SMAG/node2.html#SECTION00024100000000000000

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文