C++实现Linux终端光线追踪的相机、球体相交及畸变问题咨询
问题解答
1. 射线发射算法与z分量含义
你的射线方向计算逻辑是正确的,从A点向B点发射射线的方向向量就是B - A,使用前归一化即可。
你当前代码里ray的z分量对应视线深度轴,你现在默认相机放在z=1位置、朝向z轴负方向,z=-1代表所有射线向屏幕内侧(z减小的方向)发射,和你预设的相机朝向完全对应。
2. 相机坐标逻辑与多方向观测
你当前的相机逻辑存在设计缺陷:你只把射线原点设为了相机坐标,但射线方向是硬编码绑定世界坐标系的xy轴的,没有和相机的朝向绑定,所以修改相机x/y坐标时,射线方向没有跟着相机位置偏移,自然会出现显示异常。
要实现6个方向观测球体,你可以先给相机定义三个局部基向量:
- 前向向量
forward:相机朝向的方向 - 右向向量
right:相机右侧的方向 - 上向向量
up:相机上方的方向
后续生成射线方向时,用公式ray = (forward + xy.x * right + xy.y * up).normalize()计算,即可和相机的朝向完全绑定。比如从x轴正方向看球体,只需把forward设为(-1,0,0),right设为(0,0,1),up设为(0,1,0)即可。
3. 球心偏移后出现畸变的原因
核心问题出在你的相交判定函数存在逻辑漏洞:你只判断了射线到球心的最短距离小于等于半径,但没有校验交点是否在射线的正方向上。当pr_v_on_ray < 0时,代表最近交点在相机后方,本不该判定为相交,你当前的代码没有做这个判断。
球心在(0,0,0)时所有有效交点都在相机前方,所以刚好没有触发bug;球心偏移后,大量相机后方的区域被误判为相交,就出现了畸变。
修正后的相交判定代码如下:
bool is_intersect(vector3 camera, vector3 ray) { // 球心指向相机的向量 vector3 v = center - camera; float abs_v = v.length(); float pr_v_on_ray = ray.dot_product(v); // 新增:交点在相机后方,直接返回不相交 if (pr_v_on_ray < 0) return false; float l2 = abs_v * abs_v - pr_v_on_ray * pr_v_on_ray; return l2 <= radius * radius; }
后续旋转相机实现建议
你后续添加旋转矩阵时,只需用旋转矩阵实时计算相机的三个基向量right/up/forward,再按上述公式生成射线方向,即可实现相机绕球任意旋转的效果。
内容的提问来源于stack exchange,提问作者Vovyaklya
相关产品推荐
相关产品推荐

