mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-11-02 12:41:18 -07:00 
			
		
		
		
	FIX: Fix the benchy orientation bug
[STUDIO-1717]: 1. Add area filter during finding the orientation vectors. The vector with largest area will be selected. 2. Area_accumulation function return the accurate normals. Change-Id: I917e29a0def4904a82d30cf0a92524bbb0da14c1 (cherry picked from commit a79cf2fa89c7247cab37ebd36974529df79f0990)
This commit is contained in:
		
							parent
							
								
									8713c5ccc4
								
							
						
					
					
						commit
						ccd333e248
					
				
					 1 changed files with 47 additions and 15 deletions
				
			
		| 
						 | 
					@ -57,16 +57,19 @@ namespace orientation {
 | 
				
			||||||
// management and spatial index structures for acceleration.
 | 
					// management and spatial index structures for acceleration.
 | 
				
			||||||
class AutoOrienter {
 | 
					class AutoOrienter {
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
 | 
					    int face_count_hull;
 | 
				
			||||||
    OrientMesh *orient_mesh = NULL;
 | 
					    OrientMesh *orient_mesh = NULL;
 | 
				
			||||||
    TriangleMesh* mesh;
 | 
					    TriangleMesh* mesh;
 | 
				
			||||||
    TriangleMesh mesh_convex_hull;
 | 
					    TriangleMesh mesh_convex_hull;
 | 
				
			||||||
    Eigen::MatrixXf normals, normals_hull;
 | 
					    Eigen::MatrixXf normals, normals_quantize, normals_hull, normals_hull_quantize;
 | 
				
			||||||
    Eigen::VectorXf areas, areas_hull;
 | 
					    Eigen::VectorXf areas, areas_hull;
 | 
				
			||||||
    Eigen::VectorXf is_apperance; // whether a facet is outer apperance
 | 
					    Eigen::VectorXf is_apperance; // whether a facet is outer apperance
 | 
				
			||||||
    Eigen::MatrixXf z_projected;
 | 
					    Eigen::MatrixXf z_projected;
 | 
				
			||||||
    Eigen::VectorXf z_max, z_max_hull;  // max of projected z
 | 
					    Eigen::VectorXf z_max, z_max_hull;  // max of projected z
 | 
				
			||||||
    Eigen::VectorXf z_median;  // median of projected z
 | 
					    Eigen::VectorXf z_median;  // median of projected z
 | 
				
			||||||
    Eigen::VectorXf z_mean;  // mean of projected z
 | 
					    Eigen::VectorXf z_mean;  // mean of projected z
 | 
				
			||||||
 | 
					    std::vector<Vec3f> face_normals;
 | 
				
			||||||
 | 
					    std::vector<Vec3f> face_normals_hull;
 | 
				
			||||||
    OrientParams params;
 | 
					    OrientParams params;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -111,9 +114,9 @@ public:
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        orientations = { { 0,0,-1 } }; // original orientation
 | 
					        orientations = { { 0,0,-1 } }; // original orientation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        area_cumulation(normals, areas, 10);
 | 
					        area_cumulation_accurate(face_normals, normals_quantize, areas, 10);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        area_cumulation(normals_hull, areas_hull, 10);
 | 
					        area_cumulation_accurate(face_normals_hull, normals_hull_quantize, areas_hull, 10);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        add_supplements();
 | 
					        add_supplements();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -181,17 +184,16 @@ public:
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            int face_count = mesh->facets_count();
 | 
					            int face_count = mesh->facets_count();
 | 
				
			||||||
            auto its = mesh->its;
 | 
					            auto its = mesh->its;
 | 
				
			||||||
            auto face_normals = its_face_normals(its);
 | 
					            face_normals = its_face_normals(its);
 | 
				
			||||||
            areas = Eigen::VectorXf::Zero(face_count);
 | 
					            areas = Eigen::VectorXf::Zero(face_count);
 | 
				
			||||||
            is_apperance = Eigen::VectorXf::Zero(face_count);
 | 
					            is_apperance = Eigen::VectorXf::Zero(face_count);
 | 
				
			||||||
            normals = Eigen::MatrixXf::Zero(face_count, 3);
 | 
					            normals = Eigen::MatrixXf::Zero(face_count, 3);
 | 
				
			||||||
 | 
					            normals_quantize = Eigen::MatrixXf::Zero(face_count, 3);
 | 
				
			||||||
            for (size_t i = 0; i < face_count; i++)
 | 
					            for (size_t i = 0; i < face_count; i++)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                float area = its.facet_area(i);
 | 
					                float area = its.facet_area(i);
 | 
				
			||||||
                if (params.NEGL_FACE_SIZE > 0 && area < params.NEGL_FACE_SIZE)
 | 
					                normals.row(i) = face_normals[i];
 | 
				
			||||||
                    continue;
 | 
					                normals_quantize.row(i) = quantize_vec3f(face_normals[i]);
 | 
				
			||||||
                
 | 
					 | 
				
			||||||
                normals.row(i) = quantize_vec3f(face_normals[i]);
 | 
					 | 
				
			||||||
                areas(i) = area;
 | 
					                areas(i) = area;
 | 
				
			||||||
                is_apperance(i) = (its.get_property(i).type == EnumFaceTypes::eExteriorAppearance);
 | 
					                is_apperance(i) = (its.get_property(i).type == EnumFaceTypes::eExteriorAppearance);
 | 
				
			||||||
                count_apperance += (is_apperance(i)==1);
 | 
					                count_apperance += (is_apperance(i)==1);
 | 
				
			||||||
| 
						 | 
					@ -208,17 +210,17 @@ public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            int face_count = mesh_convex_hull.facets_count();
 | 
					            int face_count = mesh_convex_hull.facets_count();
 | 
				
			||||||
            auto its = mesh_convex_hull.its;
 | 
					            auto its = mesh_convex_hull.its;
 | 
				
			||||||
            auto face_normals = its_face_normals(its);
 | 
					            face_count_hull = mesh_convex_hull.facets_count();
 | 
				
			||||||
 | 
					            face_normals_hull = its_face_normals(its);
 | 
				
			||||||
            areas_hull = Eigen::VectorXf::Zero(face_count);
 | 
					            areas_hull = Eigen::VectorXf::Zero(face_count);
 | 
				
			||||||
            normals_hull = Eigen::MatrixXf::Zero(face_count, 3);
 | 
					            normals_hull = Eigen::MatrixXf::Zero(face_count_hull, 3);
 | 
				
			||||||
 | 
					            normals_hull_quantize = Eigen::MatrixXf::Zero(face_count_hull, 3);
 | 
				
			||||||
            for (size_t i = 0; i < face_count; i++)
 | 
					            for (size_t i = 0; i < face_count; i++)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                float area = its.facet_area(i);
 | 
					                float area = its.facet_area(i);
 | 
				
			||||||
                if (params.NEGL_FACE_SIZE > 0 && area < params.NEGL_FACE_SIZE)
 | 
					 | 
				
			||||||
                    continue;
 | 
					 | 
				
			||||||
                //normals_hull.row(i) = quantize_vec3f(face_normals[i]);
 | 
					 | 
				
			||||||
                //We cannot use quantized vector here, the accumulated error will result in bad orientations.
 | 
					                //We cannot use quantized vector here, the accumulated error will result in bad orientations.
 | 
				
			||||||
                normals_hull.row(i) = face_normals[i];
 | 
					                normals_hull.row(i) = face_normals_hull[i];
 | 
				
			||||||
 | 
					                normals_hull_quantize.row(i) = quantize_vec3f(face_normals_hull[i]);
 | 
				
			||||||
                areas_hull(i) = area;
 | 
					                areas_hull(i) = area;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -248,7 +250,37 @@ public:
 | 
				
			||||||
            BOOST_LOG_TRIVIAL(debug) << align_counts[i].first.transpose() << ", area: " << align_counts[i].second;
 | 
					            BOOST_LOG_TRIVIAL(debug) << align_counts[i].first.transpose() << ", area: " << align_counts[i].second;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    //This function is to make sure to return the accurate normal rather than quantized normal
 | 
				
			||||||
 | 
					    void area_cumulation_accurate( std::vector<Vec3f>& normals_, const Eigen::MatrixXf& quantize_normals_, const Eigen::VectorXf& areas_, int num_directions = 10)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::unordered_map<stl_normal, std::pair<std::vector<float>, Vec3f>, VecHash> alignments_;
 | 
				
			||||||
 | 
					        Vec3f n1 = { 0, 0, 0 };
 | 
				
			||||||
 | 
					        std::vector<float> current_areas = {0, 0};
 | 
				
			||||||
 | 
					        // init to 0
 | 
				
			||||||
 | 
					        for (size_t i = 0; i < areas_.size(); i++) {
 | 
				
			||||||
 | 
					            alignments_.insert(std::pair(quantize_normals_.row(i), std::pair(current_areas, n1)));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        // cumulate areas
 | 
				
			||||||
 | 
					        for (size_t i = 0; i < areas_.size(); i++)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            alignments_[quantize_normals_.row(i)].first[1] += areas_(i);
 | 
				
			||||||
 | 
					            if (areas_(i) > alignments_[quantize_normals_.row(i)].first[0]){
 | 
				
			||||||
 | 
					                alignments_[quantize_normals_.row(i)].second = normals_[i];
 | 
				
			||||||
 | 
					                alignments_[quantize_normals_.row(i)].first[0] = areas_(i);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        typedef std::pair<stl_normal, std::pair<std::vector<float>, Vec3f>> PAIR;
 | 
				
			||||||
 | 
					        std::vector<PAIR> align_counts(alignments_.begin(), alignments_.end());
 | 
				
			||||||
 | 
					        sort(align_counts.begin(), align_counts.end(), [](const PAIR& p1, const PAIR& p2) {return p1.second.first[1] > p2.second.first[1]; });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        num_directions = std::min((size_t)num_directions, align_counts.size());
 | 
				
			||||||
 | 
					        for (size_t i = 0; i < num_directions; i++)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            orientations.push_back(align_counts[i].second.second);
 | 
				
			||||||
 | 
					            BOOST_LOG_TRIVIAL(debug) << align_counts[i].second.second.transpose() << ", area: " << align_counts[i].second.first[1];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    void add_supplements()
 | 
					    void add_supplements()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        std::vector<Vec3f> vecs = { {0, 0, -1} ,{0.70710678, 0, -0.70710678},{0, 0.70710678, -0.70710678},
 | 
					        std::vector<Vec3f> vecs = { {0, 0, -1} ,{0.70710678, 0, -0.70710678},{0, 0.70710678, -0.70710678},
 | 
				
			||||||
| 
						 | 
					@ -264,7 +296,7 @@ public:
 | 
				
			||||||
    /// remove duplicate orientations
 | 
					    /// remove duplicate orientations
 | 
				
			||||||
    /// </summary>
 | 
					    /// </summary>
 | 
				
			||||||
    /// <param name="tol">tolerance. default 0.01 =sin(0.57\degree)</param>
 | 
					    /// <param name="tol">tolerance. default 0.01 =sin(0.57\degree)</param>
 | 
				
			||||||
    void remove_duplicates(double tol=0.00000001)
 | 
					    void remove_duplicates(double tol=0.0000001)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        for (auto it = orientations.begin()+1; it < orientations.end(); )
 | 
					        for (auto it = orientations.begin()+1; it < orientations.end(); )
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue