Show / Hide Table of Contents
    ///////////////////////////////////////////////////////////////////////////
    //
    //  System:    Simplygon
    //  File:      MaterialPartRemoverExample.cpp
    //  Language:  C++
    //
    //  Copyright (c) 2019 Microsoft. All rights reserved.
    //
    //  This is private property, and it is illegal to copy or distribute in
    //  any form, without written authorization by the copyright owner(s).
    //
    ///////////////////////////////////////////////////////////////////////////
    //
    //  #Description# 
    //
    //  A scene containing multiple objects of different sizes and materials are loaded. 
    //  
    //  A threshold is set per-material. If an object is smaller than the threshold
    //  corresponding with its material ID, it will be removed by the PartRemover.
    //
    //  The threshold is expressed in percent of the entire scene diameter. So if 
    //  Material 0 has threshold 10% and an object with material ID 0 is smaller than 
    //  10% of the scene, it will be removed.
    //
    //  This is useful for removing decal quads of certain sizes from the generated LOD.
    //  
    ///////////////////////////////////////////////////////////////////////////
    
    #include "../Common/Example.h"
    
    void RunExampleMaterialPartRemover( const std::string& readFrom, const std::string& writeTo );
    
    int main( int argc, char* argv[] )
        {
        try
        {
            InitExample();
    
            // Set global variable. Using Orthonormal method for calculating
            // tangentspace.
            sg->SetGlobalSetting("DefaultTBNType", SG_TANGENTSPACEMETHOD_ORTHONORMAL);
    
            std::string assetPath = GetAssetPath();
    
            // Run the example code
            RunExampleMaterialPartRemover(assetPath + "PartRemoverAssets/partRemoverScene.obj", "partRemoverScene_out");
    
            DeinitExample();
        }
        catch (const std::exception& ex)
        {
            std::cerr << ex.what() << std::endl;
            return -1;
        }
    
        return 0;
        }
    
    void RunExampleMaterialPartRemover( const std::string& readFrom, const std::string& writeTo )
        {
        std::string output_geometry_filename = GetExecutablePath() + writeTo + ".obj";
    
        // Load from file
        spWavefrontImporter objReader = sg->CreateWavefrontImporter();
        objReader->SetExtractGroups( false ); //Makes unified geometry data
        objReader->SetImportFilePath( readFrom.c_str() );
        if( !objReader->RunImport() )
            throw std::exception("Failed to load input file!");
    
        // Make a copy of all the scene geometries as a a single combined geometry
        // The triangles that belong to each individual geometry (or part-geometry) 
        // will have a GroupID to know where it belongs to.
        spScene scene = objReader->GetScene();
        spGeometryData combinedGeomCopy = scene->NewCombinedGeometry( -1 );
        spMaterialTable materials = scene->GetMaterialTable();
    
        // Calculate the extents to get a scene scale value
        combinedGeomCopy->CalculateExtents( false );
        real inf[3], sup[3], diag[3];
        combinedGeomCopy->GetInf( inf );
        combinedGeomCopy->GetSup( sup );
        for( uint i = 0; i < 3; ++i )
            diag[i] = sup[i] - inf[i];
    
        real diam = sqrtf( diag[0] * diag[0] + diag[1] * diag[1] + diag[2] * diag[2] );
    
        // Create the part remover tool
        spPartRemover partRem = sg->CreatePartRemover();
        partRem->SetGeometry( combinedGeomCopy );
    
        // Set settings
        // partRem->SetSizeThreshold( 0.2f*diam ); //This sets the global threshold, which will be ignored if the flag below is true
        partRem->SetUsePerMaterialSizeThresholds( true ); // This will make the part remover use the per-material threshold array
    
        // Setup the PerMaterialSizeThresholds array
        spRealArray perMaterialSizeThresholds = partRem->GetPerMaterialSizeThresholds();
        unsigned int matCount = materials->GetItemsCount();
        perMaterialSizeThresholds->SetItemCount( matCount );
    
        // If parts made up of material 1 have a diameter smaller than 10% of the scene's entire diameter,
        // then remove the part. Material 2 parts get removed at 20%.
        // The threshold for Material 0 is zero, meaning we never remove parts using it.
        if( matCount >= 2 )
            {
            perMaterialSizeThresholds->SetItem( 0, 0.0f );
            perMaterialSizeThresholds->SetItem( 1, 0.1f*diam );
            perMaterialSizeThresholds->SetItem( 2, 0.2f*diam );
            }
    
        // For all remaining materials
        for( uint i = 3; i < matCount; ++i )
            {
            perMaterialSizeThresholds->SetItem( i, 0.f ); //Do not remove parts consisting of these materials
            }
    
        // Run the processing
        partRem->RunPartRemoval();
    
        // Input the combined geometry with the parts removed into a new empty scene
        spScene processedScene = sg->CreateScene();
        processedScene->GetRootNode()->CreateChildMesh( combinedGeomCopy );
        processedScene->GetMaterialTable()->Copy( scene->GetMaterialTable() );
        processedScene->GetTextureTable()->Copy( scene->GetTextureTable() );
    
        // Store to file
        spWavefrontExporter objexp = sg->CreateWavefrontExporter();
    
        objexp->SetExportFilePath( output_geometry_filename.c_str() );
        objexp->SetScene( processedScene );
        objexp->RunExport();
        }
    
    Back to top Terms of Use | Privacy and cookies | Trademarks | Copyright © 2019 Microsoft