2.4 generate_ray 和 naive_intersect

请问我按照文档这样写的错误在什么地方,得到的返回值与使用 ray.cpp 的静态链接版本所得到的有些不一样
并且运行时会出现 abort() has been called 的错误
(已经修改很多次了还是不行) :sob:

已经进行试验:使用 ray.cpp 静态链接的话就能得到正确的渲染图

同学你的代码思路是没问题的,会不会是你的返回值有点问题?

这里提供一种检查 generate_ray 的方法:

在 Dandelion 中,鼠标点击拾取 (picking) 的操作也是用射线求交实现的,并且也调用了 generate_ray 这个函数。因此,你可以借助 Debug → Debug Options 中的 Show Picking Ray 这个选项来查看你生成的射线。操作方法是:

  1. 启动 Dandelion,从菜单栏上打开 Debug → Debug Options → Show Picking Ray 这个选项。
  2. 随意点击一次场景中的位置,此时程序会调用 generate_ray 生成一条从主视角位置到点击方向的射线。但由于观察位置与射线起点重合,此时看不到射线。
  3. 稍微旋转视角,此时应该会看到一条射线。这条射线应该大致上从刚才所在的位置出发,射向刚刚点击过的位置,可以借助地面方格来辅助观察。

如果你看到了射线,并且看到的射线也符合刚刚观察(点击)的位置,那么 generate_ray 应该就没有问题。

返回值我使用的就是原来的这个
return {camera.position, (world_pos - camera.position).normalized()};

主要是因为我发现函数 naive_intersect()result.t 值一直没有更新,渲染的进度条进行的非常快,所以我怀疑是光线的问题,那么就应该是 naive_intersect() 这里的问题了,但是我并没有发现错误在哪里 :sob:

trace() 中给 naive_intersect() 传递的参数如下

如果一直返回 std::nullopt,说明一直没有相交,那同学你可以检查一下是否发生过任何一次相交。如果一次都没有发生或者只有偶尔几次,说明求解出的光线的方向存在问题。如果发生的次数很正常,那就是在相交后的处理存在问题

我使用助教 @greyishsong 提供的方法,发现 generate_ray() 应该是没有问题的。
但是我在 naive_intersect() 中计算得到的 betagamma 都不在 0 - 1 之间,一次相交都没有发生

传递的参数是 naive_intersect(ray, object->mesh, object->model())

naive_intersect() 中我先进行如下变换

std::array<size_t, 3> face = mesh.face(i);
Vector3f a = mesh.vertex(face[0]);
a = (model * Vector4f(a.x(), a.y(), a.z(), 1.0f)).head(3);

计算过程如下

Vector3f S1 = (ray.direction).cross(c - a);
Vector3f S2 = (ray.origin - a).cross(b - a);

float t = S2.dot(c - a) / S1.dot(b - a);
float beta  = S1.dot(ray.origin - a) / S1.dot(b - a);
float gamma = S2.dot(ray.direction) / S1.dot(b - a);

请问可能是什么地方的问题呢 :sob:

你的计算过程我推了一下,应该是没问题的。你的实际实现代码里的 T 是 ray.origin-a 吗,如果是的话,那么你目前展示出的代码应该没太大问题,除了返回的法线方向,这个是需要你自己重新计算的,不是直接取这个 mesh 的 normal

:joy:找到问题了,就是助教 @roland 提到的返回的法线问题,我在修改了之后得到正确结果了,谢谢助教

同学,你的 ratio 是乘到哪一个向量上的,麻烦能问一下吗