Esempio n. 1
0
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);
} 
Esempio n. 2
0
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);
                }
            }
        }
    }
}
Esempio n. 3
0
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_;
} 
Esempio n. 4
0
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;
}
Esempio n. 5
0
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;
}
Esempio n. 6
0
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;
            }
        }
    }
}
Esempio n. 8
0
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);

}