我从Scratchapixel网站上借用了一些概念,特别是http:// scratchapixel .com / lessons / 3d基本渲染/最小射线追踪器渲染-简单形状/射线盒相交。
基本上,我正在生成16条射线,所有射线都来自相同的源向量。方向矢量在YZ平面上以+15度开始,并以-2度的增量继续下降到-15。我有一个轴对齐的边界框,正在与之测试交集。我使用旋转变换绕Z轴旋转16射线CCW。我正在对所有16条射线(每条0.1度)执行相交测试,如果返回true,则将点添加到点云。
这是我的相交代码:
bool test_intersect(Box b, Ray r, Vec3f& intersect_point)
{
float txmin = 0.0f, txmax = 0.0f, tymin = 0.0f, tymax = 0.0f, tzmin = 0.0f, tzmax = 0.0f;
float t_min = 0.0f, t_max = 0.0f, t = 0.0f;
// Determine inverse direction of ray to alleviate 0 = -0 issues
Vec3f inverse_direction(1 / r.direction.x, 1 / r.direction.y, 1 / r.direction.z);
// Solving box_min/box_max0 = O + Dt
txmin = (b.box_min.x - r.origin.x) * inverse_direction.x;
txmax = (b.box_max.x - r.origin.x) * inverse_direction.x;
tymin = (b.box_min.y - r.origin.y) * inverse_direction.y;
tymax = (b.box_max.y - r.origin.y) * inverse_direction.y;
tzmin = (b.box_min.z - r.origin.z) * inverse_direction.z;
tzmax = (b.box_max.z - r.origin.z) * inverse_direction.z;
// Depending on direction of ray tmin may > tmax, so we may need to swap
if (txmin > txmax) std::swap(txmin, txmax);
if (tymin > tymax) std::swap(tymin, tymax);
if (tzmin > tzmax) std::swap(tzmin, tzmax);
t_min = txmin;
t_max = txmax;
// If t-value of a min is greater than t-value of max,
// we missed the object in that plane.
if ((t_min > tymax) || (tymin > t_max))
return false;
if (tymin > t_min)
t_min = tymin;
if (tymax < t_max)
t_max = tymax;
if ((t_min > tzmax) || (tzmin > t_max))
return false;
if (tzmin > t_min)
t_min = tzmin;
if (tzmax < t_max)
t_max = tzmax;
if (t_min > 0)
t = t_min;
else
if (t_max > 0)
t = t_max;
else
return false;
intersect_point.x = r.origin.x + r.direction.x * t;
intersect_point.y = r.origin.y + r.direction.y * t;
intersect_point.z = r.origin.z + r.direction.z * t;
return true;
}
我的自转:
// Rotation around z axis, for rotating array and checking beam intersections
void transform_rotate_z(Vec3f& in_vector, float angle)
{
float radians = angle * (M_PI / 180);
float result_x = cos(radians) * in_vector.x + -sin(radians) * in_vector.y;
float result_y = sin(radians) * in_vector.x + cos(radians) * in_vector.y;
in_vector.x = result_x;
in_vector.y = result_y;
}
我已经花了很长时间了,但我似乎无法确定自己该怎么做防止这种弯曲,我确定我忽略了一些简单的事情。感谢您提供的任何帮助。
EDIT 9/18/16:事实证明我错误地认为物理LIDAR单元具有某种“拉直”曲线的算法方法,事实并非如此!输出应该看起来像上面的图片。
#1 楼
方向矢量从YZ平面上的+15度开始,并以-2度的增量继续下降到-15。
存在问题,即通过生成射线这样,您所做的更多是像球形投影或鱼眼投影,而不是线性透视投影。非线性投影是您看到的曲率的起点。
要获得透视投影,从概念上讲,它的思考方式是在摄像头前浮动一个图像矩形,分为网格正方形(像素),然后从相机位置向每个像素中心发射光线。在代码中,这类似于:
p = tan(horizontalFOV / 2)
q = tan(verticalFOV / 2)
for y = 0 to imageHeight - 1
for x = 0 to imageWidth - 1
rayDirection = Vec3f(1.0,
p * ((x + 0.5) / imageWidth * 2.0 - 1.0)
q * ((y + 0.5) / imageHeight * 2.0 - 1.0)).normalize()
请注意,以这种方式生成的方向在角度上的分布不均等(它们彼此之间的角度朝着图片而不是居中图片),但它们在图片矩形上的距离相等。
评论
$ \ begingroup $
谢谢弥敦道!我正在尝试模拟LIDAR扫描仪,因此这是扇形光束和相等角度间距的原因。我要为模拟建模的特定扫描仪的激光器处于外壳外部的扇形光束配置中,但是随着返回的通过,它们从扇形光束转向成平行光束(通过透镜)。我正在尝试找到一种维护此模型的方法,以使模拟尽可能准确。关于我该如何做的任何想法?
$ \ endgroup $
– Irongrave
16年8月10日在15:19
$ \ begingroup $
@Irongrave对不起,我对LIDAR扫描仪了解不多。您提到的镜头是否有图表或其他设置?我很难想象它。
$ \ endgroup $
–内森·里德(Nathan Reed)
16年8月10日在20:54
$ \ begingroup $
这是手册中的图片:(imgur.com/a/czhpt)
$ \ endgroup $
– Irongrave
16年8月11日在1:16
$ \ begingroup $
事实证明,我错误地认为物理LIDAR单元具有某种“拉直”曲线的算法,而事实并非如此。您的帖子帮助我得出了最终结论,非常感谢,我选择了它作为您的回答。
$ \ endgroup $
– Irongrave
16-09-19的1:51