Show / Hide Table of Contents
    ///////////////////////////////////////////////////////////////////////////
    //
    //  System:    Simplygon
    //  File:      AggregateRepeatingUVsExample.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# 
    //
    //  This example shows how to get improved texture quality from meshes that 
    //  contain lots of tiling textures when aggregating the scene materials.
    //
    //  By subdividing (cutting) the mesh along the UV-tiling seams we generate
    //  a more complex geometry with more triangles that will only have UVs in
    //  the uv = [ (0, 0) , (tileSize, tileSize) ] interval.
    //
    //  The tileSize is a user selected positive integer that determines the 
    //  cutting frequency. Smaller tileSize values (minimum 1) increases 
    //  the geometry complexity but improves the texture quality.
    //
    //  So the trade-off is that with better texture quality you get more geometry complexity.
    //
    //  Example:
    //  The scene contains a plane (two triangles) with a tiling dirt texture that
    //  gets repeated 10 times in both U and V directions. Normally if the
    //  scene is aggregated, the geometry will be exactly the same but the 
    //  output texture will contain all the (10x10=100) dirt patches put into the
    //  single texture. The output texture cannot be tiling because
    //  there might be more objects in the scene whose textures will also
    //  be aggregated into the output.
    //
    //  By enabling the subdivision based on UV tiles - the dirt mesh is cut 
    //  for every "positive multiplier" of times the texture is repeated.
    //  The output geometry contains more triangle in the plane, but the 
    //  dirt texture can be much larger. If the tileSize is 1 - the output
    //  texture will only contain one instance of the dirt texture with no 
    //  repeats.
    //
    ///////////////////////////////////////////////////////////////////////////
    
    #include "../Common/Example.h"
    
    void RunExample(const std::string& readFrom, const std::string& writeTo, int tileSize);
    
    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();
    
            for (int tileSize = 1; tileSize < 10; tileSize += 2)
            {
                std::string outputFileName = "Aggregation_UVSubdivision_TileSize_" + std::to_string(tileSize);
                RunExample(assetPath + "UVSubdivision/TilingTextures.obj", outputFileName, tileSize);
            }
    
            DeinitExample();
        }
        catch (const std::exception& ex)
        {
            std::cerr << ex.what() << std::endl;
            return -1;
        }
    
        return 0;
        }
    
    void RunExample(const std::string& readFrom, const std::string& writeTo, int tileSize)
        {
        // Load from file
        spWavefrontImporter objReader = sg->CreateWavefrontImporter();
        objReader->SetImportFilePath( readFrom.c_str() );
        if( !objReader->RunImport() )
            throw std::exception("Failed to load input file!");
    
        // Get the scene
        spScene scene = objReader->GetScene();
    
        spScene aggregatedScene = sg->CreateScene();
        aggregatedScene->DeepCopy( scene );
    
        // Create the spAggregationProcessor
        spAggregationProcessor aggregationProcessor = sg->CreateAggregationProcessor();
        // Set the input scene
        aggregationProcessor->SetScene(aggregatedScene);
    
        spAggregationSettings aggregatorSettings = aggregationProcessor->GetAggregationSettings();
    
        //Enable the subdivision
        aggregatorSettings->SetSubdivideGeometryBasedOnUVTiles(true);
        aggregatorSettings->SetSubdivisionTileSize(tileSize);
    
        // Set the BaseAtlasOnOriginalTexCoords to true so that the new texture
        // coords will be based on the original. This way the four identical
        // SimplygonMan mesh instances will still share texture coords, and
        // when packing the texture charts into the new atlas, only rotations
        // multiples of 90 degrees are allowed.
        aggregatorSettings->SetBaseAtlasOnOriginalTexCoords(true);
    
        // Get the mapping image settings, a mapping image is needed to
        // cast the new textures.
        spMappingImageSettings mappingImageSettings = aggregationProcessor->GetMappingImageSettings();
        mappingImageSettings->SetGenerateMappingImage(true);
        mappingImageSettings->SetGutterSpace(20);
        mappingImageSettings->SetWidth(512);
        mappingImageSettings->SetHeight(512);
        mappingImageSettings->SetUseFullRetexturing(true); //replace old UVs
    
        // If BaseAtlasOnOriginalTexCoords is enabled and 
        // if charts are overlapping in the original texture coords, they will be separated if
        // SeparateOverlappingCharts is set to true.
        mappingImageSettings->SetChartAggregatorSeparateOverlappingCharts(false);
    
        // Run the process
        aggregationProcessor->RunProcessing();
    
        //Clear the copied materials from the lod, and later populate it with newly generated materials
        spTextureTable lodTexTable = aggregatedScene->GetTextureTable();
        lodTexTable->Clear();
        spMaterialTable lodMatTable = aggregatedScene->GetMaterialTable();
        lodMatTable->Clear();
    
        //Create a new material that we cast the new textures onto
        spMaterial lodMaterial = sg->CreateMaterial();
        lodMaterial->SetName( "output_material" );
    
        lodMatTable->AddMaterial( lodMaterial );
        lodMatTable->SetName( "CombinedMaterials" );
    
        spColorCaster diffuseCaster = sg->CreateColorCaster();
        diffuseCaster->SetColorType( SG_MATERIAL_CHANNEL_DIFFUSE );
        diffuseCaster->SetSourceMaterials( scene->GetMaterialTable() );
        diffuseCaster->SetSourceTextures( scene->GetTextureTable() );
        std::string diffuse;
        diffuse = writeTo + ".png";
        diffuseCaster->SetOutputFilePath( diffuse.c_str() );
        diffuseCaster->SetMappingImage( aggregationProcessor->GetMappingImage() );
    
        diffuseCaster->RunProcessing();
    
        //Setup new texture in LOD scene
        AddSimplygonTexture( lodMaterial, lodTexTable, SG_MATERIAL_CHANNEL_DIFFUSE, diffuse.c_str());
    
        if (true)
            {
            // Store to file
            spWavefrontExporter objexp = sg->CreateWavefrontExporter();
            std::string output_geometry_filename = GetExecutablePath() + writeTo + ".obj";
            objexp->SetExportFilePath(output_geometry_filename.c_str());
            objexp->SetScene(aggregatedScene);
            objexp->RunExport();
            }
    
        //Create a new Scene based on the aggregated scene.
        spScene reducedScene = sg->CreateScene();
        reducedScene->DeepCopy(aggregatedScene);
    
        //Many triangles might have been created from the subdivisions
        //We run a reduction on the results. 
        spReductionProcessor red = sg->CreateReductionProcessor();
        // Set the input scene
        red->SetScene(reducedScene);
    
        spReductionSettings reductionSettings = red->GetReductionSettings();
        reductionSettings->SetOnScreenSize(500);
    
        // Run the process
        red->RunProcessing();
    
        if(true)
            {
            // Store to file
            spWavefrontExporter objexp = sg->CreateWavefrontExporter();
            std::string output_geometry_filename = GetExecutablePath() + writeTo + "_Reduced" + ".obj";
            objexp->SetExportFilePath(output_geometry_filename.c_str());
            objexp->SetScene(reducedScene);
            objexp->RunExport();
            }
        }
    
    Back to top Terms of Use | Privacy and cookies | Trademarks | Copyright © 2019 Microsoft