光线追踪--DDA算法

您所在的位置:网站首页 简述DDA算法 光线追踪--DDA算法

光线追踪--DDA算法

#光线追踪--DDA算法| 来源: 网络整理| 查看: 265

作用:

在Lidar或者RGB SLAM 使用栅格建立地图的过程中,其中的integate(不不知道怎么翻译,就叫深度值融合),或者渲染特定视角的3d场景时,我们使用光线追踪,获取与光线相交的栅格。

代码(voxelbox 的代码), 比较懒了,就不上图解释了直接上代码

// 光线追踪的class class RayCaster { public: EIGEN_MAKE_ALIGNED_OPERATOR_NEW RayCaster(const Point& origin, const Point& point_G, const bool is_clearing_ray, const bool voxel_carving_enabled, const FloatingPoint max_ray_length_m, const FloatingPoint voxel_size_inv, const FloatingPoint truncation_distance, const bool cast_from_origin = true); // 这个常用,指定光线的起始点和终止点 RayCaster(const Point& start_scaled, const Point& end_scaled); // 返回光线经过的下一个voxel的坐标 /// returns false if ray terminates at ray_index, true otherwise bool nextRayIndex(GlobalIndex* ray_index); private: void setupRayCaster(const Point& start_scaled, const Point& end_scaled); Ray t_to_next_boundary_; GlobalIndex curr_index_; AnyIndex ray_step_signs_; Ray t_step_size_; uint ray_length_in_steps_; uint current_step_; }; // 预先计算光线经过的栅格,主要是降低计算量 /** * This function assumes PRE-SCALED coordinates, where one unit = one voxel * size. The indices are also returned in this scales coordinate system, which * should map to voxel indices. */ inline void castRay(const Point& start_scaled, const Point& end_scaled, AlignedVector* indices) { CHECK_NOTNULL(indices); RayCaster ray_caster(start_scaled, end_scaled); GlobalIndex ray_index; while (ray_caster.nextRayIndex(&ray_index)) { indices->push_back(ray_index); } }

代码实现对应的解释图片在最下面(比较丑,哈哈)

// 光线追踪class 的具体实现 // This class assumes PRE-SCALED coordinates, where one unit = one voxel size. // The indices are also returned in this scales coordinate system, which should // map to voxel indices. RayCaster::RayCaster(const Point& origin, const Point& point_G, const bool is_clearing_ray, const bool voxel_carving_enabled, const FloatingPoint max_ray_length_m, const FloatingPoint voxel_size_inv, const FloatingPoint truncation_distance, const bool cast_from_origin) { const Ray unit_ray = (point_G - origin).normalized(); Point ray_start, ray_end; if (is_clearing_ray) { FloatingPoint ray_length = (point_G - origin).norm(); ray_length = std::min(std::max(ray_length - truncation_distance, static_cast(0.0)), max_ray_length_m); ray_end = origin + unit_ray * ray_length; ray_start = voxel_carving_enabled ? origin : ray_end; } else { ray_end = point_G + unit_ray * truncation_distance; ray_start = voxel_carving_enabled ? origin : (point_G - unit_ray * truncation_distance); } const Point start_scaled = ray_start * voxel_size_inv; const Point end_scaled = ray_end * voxel_size_inv; if (cast_from_origin) { setupRayCaster(start_scaled, end_scaled); } else { setupRayCaster(end_scaled, start_scaled); } } RayCaster::RayCaster(const Point& start_scaled, const Point& end_scaled) { setupRayCaster(start_scaled, end_scaled); } // returns false if ray terminates at ray_index, true otherwise bool RayCaster::nextRayIndex(GlobalIndex* ray_index) { if (current_step_++ > ray_length_in_steps_) { return false; } DCHECK(ray_index != nullptr); *ray_index = curr_index_; int t_min_idx; // 离需要穿越的边界的哪个轴越近,对应的那个轴box 坐标值加1 t_to_next_boundary_.minCoeff(&t_min_idx); curr_index_[t_min_idx] += ray_step_signs_[t_min_idx]; t_to_next_boundary_[t_min_idx] += t_step_size_[t_min_idx]; return true; } void RayCaster::setupRayCaster(const Point& start_scaled, const Point& end_scaled) { if (std::isnan(start_scaled.x()) || std::isnan(start_scaled.y()) || std::isnan(start_scaled.z()) || std::isnan(end_scaled.x()) || std::isnan(end_scaled.y()) || std::isnan(end_scaled.z())) { ray_length_in_steps_ = 0; return; } // 计算启始3d点在哪个栅格 curr_index_ = getGridIndexFromPoint(start_scaled); // 计算终止3d点的在哪个栅格 const GlobalIndex end_index = getGridIndexFromPoint(end_scaled); const GlobalIndex diff_index = end_index - curr_index_; current_step_ = 0; // 光线经过的栅格数目 ray_length_in_steps_ = std::abs(diff_index.x()) + std::abs(diff_index.y()) + std::abs(diff_index.z()); // 计算射线向量 const Ray ray_scaled = end_scaled - start_scaled; // 计算射线的正负号,表示每次栅格移动的方向 ray_step_signs_ = AnyIndex(signum(ray_scaled.x()), signum(ray_scaled.y()), signum(ray_scaled.z()));  // 计算光线下一次要穿过的边界 const AnyIndex corrected_step(std::max(0, ray_step_signs_.x()), std::max(0, ray_step_signs_.y()), std::max(0, ray_step_signs_.z())); // 计算起始点的相对于启始栅格的位置,实际上就是建立一个局部坐标系(在curr_index_处) const Point start_scaled_shifted = start_scaled - curr_index_.cast(); // 计算起始点相对于下一次要穿过边界框的位置 Ray distance_to_boundaries(corrected_step.cast() - start_scaled_shifted);  // 起始点到下一个边界的位置的  // 到下一个边界框的归一化的距离,(相对与光线的长度), t_to_next_boundary_ = Ray((std::abs(ray_scaled.x())


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3