void reduction_entropy:: update_normal(shared_surfel target_surfel_ptr, shared_entropy_surfel_vector const neighbour_ptrs) const{ vec3f new_normal(0.0, 0.0, 0.0); real weight_sum = 0.f; new_normal = target_surfel_ptr->normal(); weight_sum = 1.0; for(auto const neighbour_ptr : neighbour_ptrs){ shared_surfel target_surfel_ptr = neighbour_ptr->contained_surfel; real weight = target_surfel_ptr->radius(); weight_sum += weight; new_normal += weight * target_surfel_ptr->normal(); } if( weight_sum != 0.0 ) { new_normal /= weight_sum; } else { new_normal = vec3r(0.0, 0.0, 0.0); } target_surfel_ptr->normal() = scm::math::normalize(new_normal); }
void management_base:: check_for_nodes_within_cells(const std::vector<std::vector<size_t>>& total_depths, const std::vector<std::vector<size_t>>& total_nums) { lamure::ren::model_database* database = lamure::ren::model_database::get_instance(); for(model_t model_index = 0; model_index < database->num_models(); ++model_index) { for(size_t cell_index = 0; cell_index < visibility_grid_->get_cell_count(); ++cell_index) { // Create bounding box of view cell. const view_cell* current_cell = visibility_grid_->get_cell_at_index(cell_index); vec3r min_vertex(current_cell->get_position_center() - (current_cell->get_size() * 0.5f)); vec3r max_vertex(current_cell->get_position_center() + (current_cell->get_size() * 0.5f)); bounding_box cell_bounds(min_vertex, max_vertex); // We can get the first and last index of the nodes on a certain depth inside the bvh. unsigned int average_depth = total_depth_rendered_nodes_[model_index][cell_index] / total_num_rendered_nodes_[model_index][cell_index]; node_t start_index = database->get_model(model_index)->get_bvh()->get_first_node_id_of_depth(average_depth); node_t end_index = start_index + database->get_model(model_index)->get_bvh()->get_length_of_depth(average_depth); for(node_t node_index = start_index; node_index < end_index; ++node_index) { // Create bounding box of node. scm::gl::boxf node_bounding_box = database->get_model(model_index)->get_bvh()->get_bounding_boxes()[node_index]; vec3r min_vertex = vec3r(node_bounding_box.min_vertex()) + database->get_model(model_index)->get_bvh()->get_translation(); vec3r max_vertex = vec3r(node_bounding_box.max_vertex()) + database->get_model(model_index)->get_bvh()->get_translation(); bounding_box node_bounds(min_vertex, max_vertex); // check if the bounding boxes collide. if(cell_bounds.intersects(node_bounds)) { visibility_grid_->set_cell_visibility(cell_index, model_index, node_index, true); } } } } }
const vec3r surfel:: random_point_on_surfel() const { auto compute_orthogonal_vector = [] (scm::math::vec3f const& n) { scm::math::vec3f u(std::numeric_limits<float>::lowest(), std::numeric_limits<float>::lowest(), std::numeric_limits<float>::lowest()); if(n.z != 0.0) { u = scm::math::vec3f( 1, 1, (-n.x - n.y) / n.z); } else if (n.y != 0.0) { u = scm::math::vec3f( 1, (-n.x - n.z) / n.y, 1); } else { u = scm::math::vec3f( (-n.y - n.z)/n.x, 1, 1); } return scm::math::normalize(u); }; // implements the orthogonal method discussed here: // http://math.stackexchange.com/questions/511370/how-to-rotate-one-vector-about-another auto rotate_a_around_b_by_rad = [](vec3f const& a, vec3f const& b, double rad) { vec3f a_comp_parallel_b = (scm::math::dot(a,b) / scm::math::dot(b,b) ) * b; vec3f a_comp_orthogonal_b = a - a_comp_parallel_b; vec3f w = scm::math::cross(b, a_comp_orthogonal_b); double x_1 = std::cos(rad) / scm::math::length(a_comp_orthogonal_b); double x_2 = std::sin(rad) / scm::math::length(w); vec3f a_rot_by_rad_orthogonal_b = scm::math::length(a_comp_orthogonal_b) * (x_1 * a_comp_orthogonal_b + x_2 * w); return a_rot_by_rad_orthogonal_b + a_comp_parallel_b; }; real random_normalized_radius_extent = ((double)std::rand()/RAND_MAX); real random_angle_in_radians = 2.0 * M_PI * ((double)std::rand()/RAND_MAX); vec3f random_direction_along_surfel = scm::math::normalize(rotate_a_around_b_by_rad( compute_orthogonal_vector(normal_), normal_, random_angle_in_radians)); // see http://mathworld.wolfram.com/DiskPointPicking.html for a short discussion about // random sampling of disks return (std::sqrt(random_normalized_radius_extent) * radius_) * vec3r(random_direction_along_surfel) + pos_; }
boost::filesystem::path builder::convert_to_binary(std::string const& input_type) const{ std::cout << std::endl; std::cout << "--------------------------------" << std::endl; std::cout << "convert input file" << std::endl; std::cout << "--------------------------------" << std::endl; LOGGER_TRACE("convert to a binary file"); auto input_file = fs::canonical(fs::path(desc_.input_file)); std::shared_ptr<format_abstract> format_in{}; auto binary_file = base_path_; if (input_type == ".xyz") { binary_file += ".bin"; format_in = std::unique_ptr<format_xyz>{new format_xyz()}; } else if (input_type == ".xyz_all") { binary_file += ".bin_all"; format_in = std::unique_ptr<format_xyzall>{new format_xyzall()}; } else if (input_type == ".ply") { binary_file += ".bin"; format_in = std::unique_ptr<format_ply>{new format_ply()}; } else { LOGGER_ERROR("Unable to convert input file: Unknown file format"); return boost::filesystem::path{}; } format_bin format_out; converter conv(*format_in, format_out, desc_.buffer_size); conv.set_surfel_callback([](surfel &s, bool& keep) { if (s.pos() == vec3r(0.0,0.0,0.0)) keep = false; }); //conv.set_scale_factor(1); //conv.set_translation(vec3r(-605535.577, -5097551.573, -1468.071)); CPU_TIMER; conv.convert(input_file.string(), binary_file.string()); // LOGGER_DEBUG("Used memory: " << GetProcessUsedMemory() / 1024 / 1024 << " MiB"); return binary_file; }
boost::filesystem::path builder::downsweep(boost::filesystem::path input_file, uint16_t start_stage) const{ bool performed_outlier_removal = false; do { std::string status_suffix = ""; if ( true == performed_outlier_removal ) { status_suffix = " (after outlier removal)"; } std::cout << std::endl; std::cout << "--------------------------------" << std::endl; std::cout << "bvh properties" << status_suffix << std::endl; std::cout << "--------------------------------" << std::endl; lamure::pre::bvh bvh(memory_limit_, desc_.buffer_size, desc_.rep_radius_algo); bvh.init_tree(input_file.string(), desc_.max_fan_factor, desc_.surfels_per_node, base_path_); bvh.print_tree_properties(); std::cout << std::endl; std::cout << "--------------------------------" << std::endl; std::cout << "downsweep" << status_suffix << std::endl; std::cout << "--------------------------------" << std::endl; LOGGER_TRACE("downsweep stage"); CPU_TIMER; bvh.downsweep(desc_.translate_to_origin, input_file.string()); auto bvhd_file = add_to_path(base_path_, ".bvhd"); bvh.serialize_tree_to_file(bvhd_file.string(), true); if ((!desc_.keep_intermediate_files) && (start_stage < 1)) { // do not remove input file std::remove(input_file.string().c_str()); } input_file = bvhd_file; // LOGGER_DEBUG("Used memory: " << GetProcessUsedMemory() / 1024 / 1024 << " MiB"); if ( 3 <= start_stage ) { break; } if ( performed_outlier_removal ) { break; } if(start_stage <= 2 ) { if(desc_.outlier_ratio != 0.0) { size_t num_outliers = desc_.outlier_ratio * (bvh.nodes().size() - bvh.first_leaf()) * bvh.max_surfels_per_node(); size_t ten_percent_of_surfels = std::max( size_t(0.1 * (bvh.nodes().size() - bvh.first_leaf()) * bvh.max_surfels_per_node()), size_t(1) ); num_outliers = std::min(std::max(num_outliers, size_t(1) ), ten_percent_of_surfels); // remove at least 1 surfel, for any given ratio != 0.0 std::cout << std::endl; std::cout << "--------------------------------" << std::endl; std::cout << "outlier removal ( " << int(desc_.outlier_ratio * 100) << " percent = " << num_outliers << " surfels)" << std::endl; std::cout << "--------------------------------" << std::endl; LOGGER_TRACE("outlier removal stage"); surfel_vector kept_surfels = bvh.remove_outliers_statistically(num_outliers, desc_.number_of_outlier_neighbours); format_bin format_out; std::unique_ptr<format_abstract> dummy_format_in{new format_xyz()}; converter conv(*dummy_format_in, format_out, desc_.buffer_size); conv.set_surfel_callback([](surfel &s, bool& keep) { if (s.pos() == vec3r(0.0,0.0,0.0)) keep = false; }); auto binary_outlier_removed_file = add_to_path(base_path_, ".bin_wo_outlier"); conv.write_in_core_surfels_out(kept_surfels, binary_outlier_removed_file.string()); bvh.reset_nodes(); input_file = fs::canonical(binary_outlier_removed_file); performed_outlier_removal = true; } else { break; } } } while( true ); return input_file; }
void node_statistics:: calculate_statistics(surfel_mem_array const& mem_array) { vec3r temp_mean = vec3r(0.0, 0.0, 0.0); vec3r temp_mean_color = vec3r(0.0, 0.0, 0.0); vec3r temp_mean_normal = vec3r(0.0, 0.0, 0.0); real temp_mean_radius = 0.0; real temp_max_radius = 0.0; real temp_min_radius = std::numeric_limits<real>::max(); for(int color_comp_idx = 0; color_comp_idx < 3; ++color_comp_idx) { color_histogram_[color_comp_idx].resize(256, 0); } size_t num_contributed_surfels(0); for (size_t j = mem_array.offset(); j < mem_array.offset() + mem_array.length(); ++j) { surfel const& current_surfel = mem_array.mem_data()->at(j); if (current_surfel.radius() != 0.0) { vec3b const& surfel_color = current_surfel.color(); temp_mean += current_surfel.pos(); temp_mean_color += surfel_color; temp_mean_normal += current_surfel.normal(); real current_radius = current_surfel.radius(); temp_mean_radius += current_surfel.radius(); temp_max_radius = std::max(temp_max_radius, current_radius); temp_min_radius = std:: min(temp_min_radius, current_radius); for (int color_comp_idx = 0; color_comp_idx < 3; ++color_comp_idx) { ++(color_histogram_[color_comp_idx][surfel_color[color_comp_idx]]); } ++num_contributed_surfels; } } if (num_contributed_surfels) { temp_mean /= num_contributed_surfels; temp_mean_color /= num_contributed_surfels; temp_mean_normal /= num_contributed_surfels; temp_mean_normal = scm::math::normalize(temp_mean_normal); temp_mean_radius /= num_contributed_surfels; } else { real lowest_real = std::numeric_limits<real>::lowest(); temp_mean = vec3r(lowest_real, lowest_real, lowest_real); temp_mean_color = vec3r(lowest_real, lowest_real, lowest_real); temp_mean_normal = vec3r(lowest_real, lowest_real, lowest_real); temp_mean_radius = lowest_real; } real temp_sd = 0.0; real temp_color_sd = 0.0; real temp_normal_sd = 0.0; real temp_radius_sd = 0.0; if(num_contributed_surfels) { for (size_t j = mem_array.offset(); j < mem_array.offset() + mem_array.length(); ++j) { surfel const& current_surfel = mem_array.mem_data()->at(j); temp_sd += std::pow(scm::math::length(temp_mean - current_surfel.pos() ), 2); temp_color_sd += std::pow(scm::math::length(temp_mean_color - current_surfel.color()), 2); temp_normal_sd += std::pow(scm::math::length(temp_mean_normal - current_surfel.normal()), 2); temp_radius_sd += std::pow((temp_mean_radius - current_surfel.radius()),2); } temp_sd = std::sqrt(temp_sd / num_contributed_surfels); temp_color_sd = std::sqrt( temp_color_sd / num_contributed_surfels); temp_normal_sd = std::sqrt( temp_normal_sd / num_contributed_surfels); temp_radius_sd = std::sqrt( temp_radius_sd / num_contributed_surfels); } else { real lowest_real = std::numeric_limits<real>::lowest(); temp_sd = lowest_real; temp_color_sd = lowest_real; temp_normal_sd = lowest_real; temp_radius_sd = lowest_real; } mean_pos_ = temp_mean; pos_sd_ = temp_sd; mean_color_ = temp_mean_color; color_sd_ = temp_color_sd; mean_normal_ = temp_mean_normal; normal_sd_ = temp_normal_sd; mean_radius_ = temp_mean_radius; radius_sd_ = temp_radius_sd; }
static void testnsevdproblem(const ap::real_2d_array& a, int n, double& vecerr, double& valonlydiff, bool& wfailed) { double mx; int i; int j; int k; int vjob; bool needl; bool needr; ap::real_1d_array wr0; ap::real_1d_array wi0; ap::real_1d_array wr1; ap::real_1d_array wi1; ap::real_1d_array wr0s; ap::real_1d_array wi0s; ap::real_1d_array wr1s; ap::real_1d_array wi1s; ap::real_2d_array vl; ap::real_2d_array vr; ap::real_1d_array vec1r; ap::real_1d_array vec1i; ap::real_1d_array vec2r; ap::real_1d_array vec2i; ap::real_1d_array vec3r; ap::real_1d_array vec3i; double curwr; double curwi; double vt; double tmp; vec1r.setbounds(0, n-1); vec2r.setbounds(0, n-1); vec3r.setbounds(0, n-1); vec1i.setbounds(0, n-1); vec2i.setbounds(0, n-1); vec3i.setbounds(0, n-1); wr0s.setbounds(0, n-1); wr1s.setbounds(0, n-1); wi0s.setbounds(0, n-1); wi1s.setbounds(0, n-1); mx = 0; for(i = 0; i <= n-1; i++) { for(j = 0; j <= n-1; j++) { if( fabs(a(i,j))>mx ) { mx = fabs(a(i,j)); } } } if( mx==0 ) { mx = 1; } // // Load values-only // if( !rmatrixevd(a, n, 0, wr0, wi0, vl, vr) ) { wfailed = false; return; } // // Test different jobs // for(vjob = 1; vjob <= 3; vjob++) { needr = vjob==1||vjob==3; needl = vjob==2||vjob==3; if( !rmatrixevd(a, n, vjob, wr1, wi1, vl, vr) ) { wfailed = false; return; } // // Test values: // 1. sort by real part // 2. test // ap::vmove(&wr0s(0), &wr0(0), ap::vlen(0,n-1)); ap::vmove(&wi0s(0), &wi0(0), ap::vlen(0,n-1)); for(i = 0; i <= n-1; i++) { for(j = 0; j <= n-2-i; j++) { if( wr0s(j)>wr0s(j+1) ) { tmp = wr0s(j); wr0s(j) = wr0s(j+1); wr0s(j+1) = tmp; tmp = wi0s(j); wi0s(j) = wi0s(j+1); wi0s(j+1) = tmp; } } } ap::vmove(&wr1s(0), &wr1(0), ap::vlen(0,n-1)); ap::vmove(&wi1s(0), &wi1(0), ap::vlen(0,n-1)); for(i = 0; i <= n-1; i++) { for(j = 0; j <= n-2-i; j++) { if( wr1s(j)>wr1s(j+1) ) { tmp = wr1s(j); wr1s(j) = wr1s(j+1); wr1s(j+1) = tmp; tmp = wi1s(j); wi1s(j) = wi1s(j+1); wi1s(j+1) = tmp; } } } for(i = 0; i <= n-1; i++) { valonlydiff = ap::maxreal(valonlydiff, fabs(wr0s(i)-wr1s(i))); valonlydiff = ap::maxreal(valonlydiff, fabs(wi0s(i)-wi1s(i))); } // // Test right vectors // if( needr ) { k = 0; while(k<=n-1) { if( wi1(k)==0 ) { ap::vmove(vec1r.getvector(0, n-1), vr.getcolumn(k, 0, n-1)); for(i = 0; i <= n-1; i++) { vec1i(i) = 0; } curwr = wr1(k); curwi = 0; } if( wi1(k)>0 ) { ap::vmove(vec1r.getvector(0, n-1), vr.getcolumn(k, 0, n-1)); ap::vmove(vec1i.getvector(0, n-1), vr.getcolumn(k+1, 0, n-1)); curwr = wr1(k); curwi = wi1(k); } if( wi1(k)<0 ) { ap::vmove(vec1r.getvector(0, n-1), vr.getcolumn(k-1, 0, n-1)); ap::vmoveneg(vec1i.getvector(0, n-1), vr.getcolumn(k, 0, n-1)); curwr = wr1(k); curwi = wi1(k); } for(i = 0; i <= n-1; i++) { vt = ap::vdotproduct(&a(i, 0), &vec1r(0), ap::vlen(0,n-1)); vec2r(i) = vt; vt = ap::vdotproduct(&a(i, 0), &vec1i(0), ap::vlen(0,n-1)); vec2i(i) = vt; } ap::vmove(&vec3r(0), &vec1r(0), ap::vlen(0,n-1), curwr); ap::vsub(&vec3r(0), &vec1i(0), ap::vlen(0,n-1), curwi); ap::vmove(&vec3i(0), &vec1r(0), ap::vlen(0,n-1), curwi); ap::vadd(&vec3i(0), &vec1i(0), ap::vlen(0,n-1), curwr); for(i = 0; i <= n-1; i++) { vecerr = ap::maxreal(vecerr, fabs(vec2r(i)-vec3r(i))); vecerr = ap::maxreal(vecerr, fabs(vec2i(i)-vec3i(i))); } k = k+1; } } // // Test left vectors // if( needl ) { k = 0; while(k<=n-1) { if( wi1(k)==0 ) { ap::vmove(vec1r.getvector(0, n-1), vl.getcolumn(k, 0, n-1)); for(i = 0; i <= n-1; i++) { vec1i(i) = 0; } curwr = wr1(k); curwi = 0; } if( wi1(k)>0 ) { ap::vmove(vec1r.getvector(0, n-1), vl.getcolumn(k, 0, n-1)); ap::vmove(vec1i.getvector(0, n-1), vl.getcolumn(k+1, 0, n-1)); curwr = wr1(k); curwi = wi1(k); } if( wi1(k)<0 ) { ap::vmove(vec1r.getvector(0, n-1), vl.getcolumn(k-1, 0, n-1)); ap::vmoveneg(vec1i.getvector(0, n-1), vl.getcolumn(k, 0, n-1)); curwr = wr1(k); curwi = wi1(k); } for(j = 0; j <= n-1; j++) { vt = ap::vdotproduct(vec1r.getvector(0, n-1), a.getcolumn(j, 0, n-1)); vec2r(j) = vt; vt = ap::vdotproduct(vec1i.getvector(0, n-1), a.getcolumn(j, 0, n-1)); vec2i(j) = -vt; } ap::vmove(&vec3r(0), &vec1r(0), ap::vlen(0,n-1), curwr); ap::vadd(&vec3r(0), &vec1i(0), ap::vlen(0,n-1), curwi); ap::vmove(&vec3i(0), &vec1r(0), ap::vlen(0,n-1), curwi); ap::vsub(&vec3i(0), &vec1i(0), ap::vlen(0,n-1), curwr); for(i = 0; i <= n-1; i++) { vecerr = ap::maxreal(vecerr, fabs(vec2r(i)-vec3r(i))); vecerr = ap::maxreal(vecerr, fabs(vec2i(i)-vec3i(i))); } k = k+1; } } } }
void bvh_stream:: read_bvh(const std::string& filename, bvh& bvh) { open_stream(filename, bvh_stream_type::BVH_STREAM_IN); if (type_ != BVH_STREAM_IN) { throw std::runtime_error( "PLOD: bvh_stream::Failed to read bvh from: " + filename_); } if (!file_.is_open()) { throw std::runtime_error( "PLOD: bvh_stream::Failed to read bvh from: " + filename_); } //scan stream file_.seekg(0, std::ios::end); size_t filesize = (size_t)file_.tellg(); file_.seekg(0, std::ios::beg); num_segments_ = 0; bvh_tree_seg tree; bvh_tree_extension_seg tree_ext; std::vector<bvh_node_seg> nodes; std::vector<bvh_node_extension_seg> nodes_ext; uint32_t tree_id = 0; uint32_t tree_ext_id = 0; uint32_t node_id = 0; uint32_t node_ext_id = 0; //go through entire stream and fetch the segments while (true) { bvh_sig sig; sig.deserialize(file_); if (sig.signature_[0] != 'B' || sig.signature_[1] != 'V' || sig.signature_[2] != 'H' || sig.signature_[3] != 'X') { throw std::runtime_error( "PLOD: bvh_stream::Invalid magic encountered: " + filename_); } size_t anchor = (size_t)file_.tellg(); switch (sig.signature_[4]) { case 'F': { //"BVHXFILE" bvh_file_seg seg; seg.deserialize(file_); break; } case 'T': { switch (sig.signature_[5]) { case 'R': { //"BVHXTREE" tree.deserialize(file_); ++tree_id; break; } case 'E': { //"BVHXTEXT" tree_ext.deserialize(file_); ++tree_ext_id; break; } default: { throw std::runtime_error( "PLOD: bvh_stream::Stream corrupt -- Invalid segment encountered"); break; } } break; } case 'N': { switch (sig.signature_[5]) { case 'O': { //"BVHXNODE" bvh_node_seg node; node.deserialize(file_); nodes.push_back(node); if (node_id != node.node_id_) { throw std::runtime_error( "PLOD: bvh_stream::Stream corrupt -- Invalid node order"); } ++node_id; break; } case 'E': { //"BVHXNEXT" bvh_node_extension_seg node_ext; node_ext.deserialize(file_); nodes_ext.push_back(node_ext); if (node_ext_id != node_ext.node_id_) { throw std::runtime_error( "PLOD: bvh_stream::Stream corrupt -- Invalid node extension order"); } ++node_ext_id; break; } default: { throw std::runtime_error( "PLOD: bvh_stream::Stream corrupt -- Invalid segment encountered"); break; } } break; } default: { throw std::runtime_error( "PLOD: bvh_stream::file corrupt -- Invalid segment encountered"); break; } } if (anchor + sig.allocated_size_ < filesize) { file_.seekg(anchor + sig.allocated_size_, std::ios::beg); } else { break; } } close_stream(false); if (tree_id != 1) { throw std::runtime_error( "PLOD: bvh_stream::Stream corrupt -- Invalid number of bvh segments"); } if (tree_ext_id > 1) { throw std::runtime_error( "PLOD: bvh_stream::Stream corrupt -- Invalid number of bvh extensions"); } //Note: This is the preprocessing library version of the file reader! //setup bvh bvh.set_depth(tree.depth_); bvh.set_fan_factor(tree.fan_factor_); bvh.set_max_surfels_per_node(tree.max_surfels_per_node_); scm::math::vec3f translation(tree.translation_.x_, tree.translation_.y_, tree.translation_.z_); bvh.set_translation(vec3r(translation)); if (tree.num_nodes_ != node_id) { throw std::runtime_error( "PLOD: bvh_stream::Stream corrupt -- Invalid number of node segments"); } if (tree_ext_id > 0) { if (tree.num_nodes_ != node_ext_id) { throw std::runtime_error( "PLOD: bvh_stream::Stream corrupt -- Invalid number of node extensions"); } } std::vector<shared_file> level_temp_files; bvh::state_type current_state = static_cast<bvh::state_type>(tree.state_); //check if intermediate state bool interm_state = current_state == bvh::state_type::after_downsweep || current_state == bvh::state_type::after_upsweep; boost::filesystem::path base_path; if (interm_state) { if (tree_ext_id != 1) { throw std::runtime_error( "PLOD: bvh_stream::Stream corrupt -- Stream is missing tree extension"); } //working_directory = tree_ext.working_directory_.string_; //basename_ = boost::filesystem::path(tree_ext.filename_.string_); base_path = boost::filesystem::path(tree_ext.filename_.string_); //setup level temp files for (uint32_t i = 0; i < tree_ext.num_disk_accesses_; ++i) { level_temp_files.push_back(std::make_shared<file>()); level_temp_files.back()->open(tree_ext.disk_accesses_[i].string_, false); } } else { base_path = boost::filesystem::canonical(boost::filesystem::path(filename)); base_path.replace_extension(""); } bvh.set_base_path(base_path); //setup nodes std::vector<bvh_node> bvh_nodes(tree.num_nodes_); for (uint32_t i = 0; i < tree.num_nodes_; ++i) { const auto& node = nodes[i]; if (i != node.node_id_) { throw std::runtime_error( "PLOD: bvh_stream::Stream corrupt -- Invalid node ordering"); } scm::math::vec3f centroid(node.centroid_.x_, node.centroid_.y_, node.centroid_.z_); scm::math::vec3f box_min(node.bounding_box_.min_.x_, node.bounding_box_.min_.y_, node.bounding_box_.min_.z_); scm::math::vec3f box_max(node.bounding_box_.max_.x_, node.bounding_box_.max_.y_, node.bounding_box_.max_.z_); if (interm_state) { const auto& node_ext = nodes_ext[i]; if (i != node_ext.node_id_) { throw std::runtime_error( "PLOD: bvh_stream::Stream corrupt -- Invalid extension ordering"); } if (node_ext.empty_ == 1) { bvh_nodes[i] = bvh_node(node.node_id_, node.depth_, bounding_box(vec3r(box_min), vec3r(box_max))); } else { const auto& disk_array = node_ext.disk_array_; surfel_disk_array sdarray = surfel_disk_array(level_temp_files[disk_array.disk_access_ref_], disk_array.offset_, disk_array.length_); bvh_nodes[i] = bvh_node(node.node_id_, node.depth_, bounding_box(vec3r(box_min), vec3r(box_max)), sdarray); } } else { //init empty nodes. We don't use surfelDIskArray //because we deal with serialized data bvh_nodes[i] = bvh_node(node.node_id_, node.depth_, bounding_box(vec3r(box_min), vec3r(box_max))); } //set node params bvh_nodes[i].set_reduction_error(node.reduction_error_); bvh_nodes[i].set_centroid(vec3r(centroid)); bvh_nodes[i].set_avg_surfel_radius(node.avg_surfel_radius_); bvh_nodes[i].set_visibility((bvh_node::node_visibility)node.visibility_); bvh_nodes[i].set_max_surfel_radius_deviation(node.max_surfel_radius_deviation_); } bvh.set_first_leaf(tree.num_nodes_ - std::pow(tree.fan_factor_, tree.depth_)); bvh.set_state(current_state); bvh.set_nodes(bvh_nodes); }