Math 光线三角形相交的光线变换

Math 光线三角形相交的光线变换,math,opengl,matrix,3d,raytracing,Math,Opengl,Matrix,3d,Raytracing,在openGL中,我有一个3D模型,我正在上面执行一个光线三角形相交,使用“快速、最小存储光线/三角形相交”(Fast,Minimum Storage ray/triangle intersection)一文中解释的代码 使用以下代码将光标位置取消投影到世界空间: bool SCamera::unproject(Vector3 input, Vector3 & output){ GLint viewport[4]; glGetIntegerv(GL_VIEWPORT,view

在openGL中,我有一个3D模型,我正在上面执行一个光线三角形相交,使用“快速、最小存储光线/三角形相交”(Fast,Minimum Storage ray/triangle intersection)一文中解释的代码

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

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();
出于某种原因,这不起作用。我是不是弄错了?还是转换错误?

一种方法可能是:

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

一种方法可能是:


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

因此,我最终实现了此功能,尽管我对如何操作不满意。在我的例子中,单个模型旋转在渲染之前作为变换应用,因此我必须通过modelview矩阵变换目标三角形

我在上面试图做的是计算一条射线,它也可以达到同样的目的,通过移动射线的原点使其围绕对象旋转,就好像对象已经旋转一样。不幸的是,我不能完全正确地计算


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

所以我终于让它工作了,尽管我对如何工作不满意。在我的例子中,单个模型旋转在渲染之前作为变换应用,因此我必须通过modelview矩阵变换目标三角形

我在上面试图做的是计算一条射线,它也可以达到同样的目的,通过移动射线的原点使其围绕对象旋转,就好像对象已经旋转一样。不幸的是,我不能完全正确地计算


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

我的解决方案是按照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)
。如果不投射这两个点,第一个点的结果就是你的原点,差异就是你的方向


祝你好运

我的解决方案是按照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)
。如果不投射这两个点,第一个点的结果就是你的原点,差异就是你的方向

祝你好运

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

NewRayPosition = Vector3.Transform(OldRay.Position, Matrix.Invert(Transformation);
NewRayDirection = Vector3.Transform(OldRay.Direction, Matrix.Invert(Rotation*Scale));
NewRayDirection.Normalize();
将光线位置与平移、缩放和旋转相乘,但方向仅与缩放和旋转相乘。由于性能原因,以您的方式进行操作是不可接受的。 详情如下:

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

NewRayPosition = Vector3.Transform(OldRay.Position, Matrix.Invert(Transformation);
NewRayDirection = Vector3.Transform(OldRay.Direction, Matrix.Invert(Rotation*Scale));
NewRayDirection.Normalize();
将光线位置与平移、缩放和旋转相乘,但方向仅与缩放和旋转相乘。由于性能原因,以您的方式进行操作是不可接受的。 详情如下:

太棒了!这是一种很好的调试我没有想到的东西的方法。谢谢。不幸的是,我仍然有麻烦。你介意上厕所吗