INLINE void mem_incr(struct svalue *var) { switch(var->type) { case T_FUNCTION: function_size += sizeof (struct closure); num_func++; if (var->u.func->funargs) mem_array(var->u.func->funargs); break; case T_MAPPING: mapping_elem += var->u.map->size; num_map++; mem_mapping(var->u.map); break; case T_POINTER: array_elem += var->u.vec->size; num_arr++; mem_array(var->u.vec); break; case T_STRING: string_size += strlen(var->u.string); num_string++; break; case T_OBJECT: /* Check for destructed objects while we'r at it :) */ if (var->u.ob->flags & O_DESTRUCTED) { num_num++; free_svalue(var); break; } num_ob++; break; case T_FLOAT: num_float++; break; case T_NUMBER: num_num++; break; default: ; } }
surfel_mem_array reduction_entropy:: create_lod(real& reduction_error, const std::vector<surfel_mem_array*>& input, const uint32_t surfels_per_node, const bvh& tree, const size_t start_node_id) const { //create output array surfel_mem_array mem_array(std::make_shared<surfel_vector>(surfel_vector()), 0, 0); //container for all input surfels including entropy (entropy_surfel_array = ESA) shared_entropy_surfel_vector entropy_surfel_array; //priority queue as vector with min entropy surfels at the back shared_entropy_surfel_vector min_entropy_surfel_ptr_queue; //final surfels shared_entropy_surfel_vector finalized_surfels; // wrap all surfels of the input array to entropy_surfels and push them in the ESA for (size_t node_id = 0; node_id < input.size(); ++node_id) { for (size_t surfel_id = input[node_id]->offset(); surfel_id < input[node_id]->offset() + input[node_id]->length(); ++surfel_id){ //this surfel will be referenced in the entropy surfel auto current_surfel = input[node_id]->mem_data()->at(input[node_id]->offset() + surfel_id); // ignore outlier radii of any kind if (current_surfel.radius() == 0.0) { continue; } //create new entropy surfel entropy_surfel current_entropy_surfel(current_surfel, surfel_id, node_id); // only place where shared pointers should be created entropy_surfel_array.push_back( std::make_shared<entropy_surfel>(current_entropy_surfel) ); } } // iterate all wrapped surfels for ( auto& current_entropy_surfel_ptr : entropy_surfel_array ){ shared_entropy_surfel_vector overlapping_neighbour_ptrs = get_locally_overlapping_neighbours(current_entropy_surfel_ptr, entropy_surfel_array); //assign/compute missing attributes current_entropy_surfel_ptr->neighbours = overlapping_neighbour_ptrs; update_entropy( current_entropy_surfel_ptr, overlapping_neighbour_ptrs); //if overlapping neighbours were found, put the entropy surfel back into the priority_queue if( !overlapping_neighbour_ptrs.empty() ) { min_entropy_surfel_ptr_queue.push_back( current_entropy_surfel_ptr ); } else { //otherwise, consider this surfel to be finalized //std::cout << "**Pushing into finalized surfels (size so far: "<<finalized_surfels.size() << "): " << (int)current_entropy_surfel_ptr->contained_surfel->color()[0] << "\n"; finalized_surfels.push_back( current_entropy_surfel_ptr ); //std::cout << "did not find any Neighbours!!!!\n"; //std::cout << current_entropy_surfel_ptr->contained_surfel->pos() << " -- " << current_entropy_surfel_ptr->contained_surfel->radius() << " ------\n"; } } // the queue was modified, therefore it is resorted std::sort(min_entropy_surfel_ptr_queue.begin(), min_entropy_surfel_ptr_queue.end(), min_entropy_order()); size_t num_valid_surfels = min_entropy_surfel_ptr_queue.size() + finalized_surfels.size(); while(true) { if( !min_entropy_surfel_ptr_queue.empty() ){ shared_entropy_surfel current_entropy_surfel = min_entropy_surfel_ptr_queue.back(); min_entropy_surfel_ptr_queue.pop_back(); //the back element is still valid, so we still got something to do if(current_entropy_surfel->validity){ //std::cout << "Working on the surfel\n"; // if merge returns true, the surfel still has neighbours if( merge(current_entropy_surfel, entropy_surfel_array, num_valid_surfels, surfels_per_node) ) { min_entropy_surfel_ptr_queue.push_back(current_entropy_surfel); /*min_entropy_surfel_ptr_queue.insert(min_entropy_surfel_ptr_queue.end(), finalized_surfels.begin(), finalized_surfels.end()); */ //finalized_surfels.clear(); } else { //otherwise we can push it directly into the finalized surfel list finalized_surfels.push_back(current_entropy_surfel); } std::sort(min_entropy_surfel_ptr_queue.begin(), min_entropy_surfel_ptr_queue.end(), min_entropy_order()); if(num_valid_surfels <= surfels_per_node) { break; } else { //break } } } else { break; } } // put valid surfels into final array //end of entropy simplification while( (!min_entropy_surfel_ptr_queue.empty()) ) { shared_entropy_surfel en_surfel_to_push = min_entropy_surfel_ptr_queue.back(); if(en_surfel_to_push->validity == true) { finalized_surfels.push_back(en_surfel_to_push); } min_entropy_surfel_ptr_queue.pop_back(); } std::sort(finalized_surfels.begin(), finalized_surfels.end(), min_entropy_order()); while( num_valid_surfels > surfels_per_node ) { auto const& min_entropy_surfel = finalized_surfels.back(); if(min_entropy_surfel->validity) { --num_valid_surfels; } finalized_surfels.pop_back(); } size_t chosen_surfels = 0; for(auto const& en_surf : finalized_surfels) { if(en_surf->validity) { if(chosen_surfels++ < surfels_per_node) { mem_array.mem_data()->push_back(*(en_surf->contained_surfel)); } else { break; } } } mem_array.set_length(mem_array.mem_data()->size()); reduction_error = 0.0; return mem_array; };
surfel_mem_array reduction_spatially_subdivided_random:: create_lod(real& reduction_error, const std::vector<surfel_mem_array*>& input, const uint32_t surfels_per_node, const bvh& tree, const size_t start_node_id) const { surfel_mem_array mem_array(std::make_shared<surfel_vector>(surfel_vector()), 0, 0); std::vector<surfel> already_picked_surfel; std::vector<surfel> original_surfels; auto const& tree_nodes = tree.nodes(); auto combined_bounding_box = tree_nodes[start_node_id].get_bounding_box(); for( uint8_t non_first_child_ids = 1; non_first_child_ids < tree.fan_factor(); ++non_first_child_ids) { auto const& sibling_bb = tree_nodes[start_node_id + non_first_child_ids].get_bounding_box(); combined_bounding_box.expand( sibling_bb.max() ); combined_bounding_box.expand( sibling_bb.min() ); } uint32_t const num_divisions_for_shortest_axis = 8; vec3r step_length(-1.0, -1.0, -1.0); uint8_t shortest_axis = -1; real min_length = std::numeric_limits<real>::max(); vec3r axis_lengths = combined_bounding_box.max() - combined_bounding_box.min(); for( uint8_t axis_idx = 0; axis_idx < 3; ++axis_idx ) { if( axis_lengths[axis_idx] < min_length ) { min_length = axis_lengths[axis_idx]; shortest_axis = axis_idx; } } step_length[shortest_axis] = axis_lengths[shortest_axis] / num_divisions_for_shortest_axis; vec3b steps_per_axis(-1,-1,-1); steps_per_axis[shortest_axis] = num_divisions_for_shortest_axis; for( uint8_t axis_idx = 0; axis_idx < 3; ++axis_idx ) { if (axis_idx != shortest_axis) { uint32_t num_axis_steps = std::max(1, int(std::ceil( axis_lengths[axis_idx] / step_length[shortest_axis] ) ) ); step_length[axis_idx] = axis_lengths[axis_idx] / num_axis_steps; steps_per_axis[axis_idx] = num_axis_steps; } } std::vector< std::vector<surfel> > spatially_divided_surfels; spatially_divided_surfels.resize( steps_per_axis[0]*steps_per_axis[1]*steps_per_axis[2] ); for (size_t node_id = 0; node_id < input.size(); ++node_id) { for (size_t surfel_id = input[node_id]->offset(); surfel_id < input[node_id]->offset() + input[node_id]->length(); ++surfel_id){ //this surfel will be referenced in the entropy surfel auto current_surfel = input[node_id]->mem_data()->at(input[node_id]->offset() + surfel_id); // ignore outlier radii of any kind if (current_surfel.radius() == 0.0) { continue; } uint32_t x_summand = std::max(uint8_t(0), std::min( uint8_t( steps_per_axis[0] - 1), uint8_t( ( current_surfel.pos()[0] - combined_bounding_box.min()[0] ) / ( combined_bounding_box.max()[0] - combined_bounding_box.min()[0] ) * steps_per_axis[0]) ) ) * steps_per_axis[1] * steps_per_axis[2]; uint32_t y_summand = std::max(uint8_t(0), std::min( uint8_t(steps_per_axis[1] - 1), uint8_t( ( current_surfel.pos()[1] - combined_bounding_box.min()[1] ) / ( combined_bounding_box.max()[1] - combined_bounding_box.min()[1] ) * steps_per_axis[1]) ) ) * steps_per_axis[2]; uint32_t z_summand = std::max(uint8_t(0), std::min( uint8_t(steps_per_axis[2] - 1), uint8_t( ( current_surfel.pos()[2] - combined_bounding_box.min()[2] ) / ( combined_bounding_box.max()[2] - combined_bounding_box.min()[2] ) * steps_per_axis[2]) ) ); uint32_t box_id = x_summand + y_summand + z_summand; spatially_divided_surfels[box_id].push_back(current_surfel); original_surfels.push_back(current_surfel); } } std::sort(std::begin(spatially_divided_surfels), std::end(spatially_divided_surfels), [](std::vector<surfel> const& lhs, std::vector<surfel> const& rhs) { return lhs.size() > rhs.size();}); while( spatially_divided_surfels.back().empty() ){ spatially_divided_surfels.pop_back(); } std::set<size_t> picked_box_ids; while( already_picked_surfel.size () < surfels_per_node ) { size_t box_id; do { box_id = rand() % spatially_divided_surfels.size(); } while(picked_box_ids.find(box_id) != picked_box_ids.end()); picked_box_ids.insert(box_id); if( picked_box_ids.size() == spatially_divided_surfels.size() ) { picked_box_ids.clear(); } auto& current_surfel_box = spatially_divided_surfels[box_id]; int32_t surf_id; surf_id = rand() % current_surfel_box.size(); surfel picked_surfel = current_surfel_box[surf_id]; already_picked_surfel.push_back(picked_surfel); current_surfel_box.erase(current_surfel_box.begin() + surf_id); if(current_surfel_box.empty()) { spatially_divided_surfels.erase( spatially_divided_surfels.begin() + box_id); if(picked_box_ids.find(box_id) != picked_box_ids.end()) picked_box_ids.erase(box_id); } } for (auto& final_candidate : already_picked_surfel) { interpolate_approx_natural_neighbours(final_candidate, original_surfels, tree); mem_array.mem_data()->push_back(final_candidate); } mem_array.set_length(mem_array.mem_data()->size()); reduction_error = 0.0; return mem_array; }