Show / Hide Table of Contents
    ///////////////////////////////////////////////////////////////////////////
    //
    //  System:    Simplygon
    //  File:      ChartAggregatorExample.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# 
    //  
    //  Sets up a scene from an OBJ file and creates an aggregate
    //  UV layout for all mesh parts, while preserving original charts.
    //  Four different layouts are produced, where charts are scaled differently:
    //  - Equal scaling
    //  - Scaling weighted based on the charts' corresponding area in 3D space
    //  - Scaling weighted based on the corresponding material texture sizes
    //  - Scaling charts to perfectly reproduce the pixel density of the input textures
    //
    //  To view the results, load the outputted scenes and view the texture coords.
    //
    //  No new materials are baked in this example, only new UVs are computed.
    //  Check out AggregationProcessorExample for aggregating scenes and baking
    //  the materials.
    //
    ///////////////////////////////////////////////////////////////////////////
    
    #include "../Common/Example.h"
    
    void RunChartAggregation(const std::string& readFrom,
        const std::string& writeToUnWeighted,
        const std::string& writeToAreaWeighted,
        const std::string& writeToOriginalTextureWeighted,
        const std::string& writeToPreserveOriginalUVDensity);
    
    int main(int argc, char* argv[])
    {
        try
        {
            InitExample();
    
            std::string assetPath = GetAssetPath();
    
            // Run the example code
            //
            RunChartAggregation(assetPath + "TexturedPlanes/texturedplanes.obj", "result_unweighted", "result_areaWeighted", "result_originalTextureWeighted", "result_PreserveOriginalUVDensity");
    
            DeinitExample();
        }
        catch (const std::exception& ex)
        {
            std::cerr << ex.what() << std::endl;
            return -1;
        }
    
        return 0;
    }
    
    
    void RunChartAggregation(const std::string& readFrom,
        const std::string& writeToUnWeighted,
        const std::string& writeToAreaWeighted,
        const std::string& writeToOriginalTextureWeighted,
        const std::string& writeToPreserveOriginalUVDensity
        )
    {
    
        std::string exePath = GetExecutablePath();
    
        // Import geometries from a file and optimize them. 
        //
        std::string output_unweighted_filename = exePath + writeToUnWeighted + ".obj";
        std::string output_areaweighted_filename = exePath + writeToAreaWeighted + ".obj";
        std::string output_textureweighted_filename = exePath + writeToOriginalTextureWeighted + ".obj";
        std::string output_preservedpixeldensity_filename = exePath + writeToPreserveOriginalUVDensity + ".obj";
    
        // Load object from file.
        // Have the importer combine all groups into one geometry.
        //
        spWavefrontImporter objReader = sg->CreateWavefrontImporter();
        objReader->SetExtractGroups(false);
        objReader->SetImportFilePath(readFrom.c_str());
        if (!objReader->RunImport())
            throw std::exception("Failed to load input file!");
    
        spScene scene = objReader->GetScene();
        spSceneMesh sceneMesh = SafeCast<ISceneMesh>(scene->GetRootNode()->GetChild(0));
        spGeometryData originalGeometry = sceneMesh->GetGeometry();
    
        // The working geometry have multiple overlapping UV charts, since
        // several meshes were combined into one geometry.
        // Now, create new chart-disjoint UV layouts by running the
        // chart aggregator.
        //
        spChartAggregator chartAggregator = sg->CreateChartAggregator();
    
        // If multiple parts of the mesh have the same texcoords, you can either select to
        // only generate one instance of the repeating texture or one instance for each
        // time it is used. This is controlled with the SeparateOverlappingCharts flag. 
        // If charts are overlapping in the original texture coords, they will be separated if
        // SeparateOverlappingCharts is set to true. 
        //
        chartAggregator->SetSeparateOverlappingCharts(true);
    
        chartAggregator->SetMaterialTable(scene->GetMaterialTable());
        chartAggregator->SetTextureTable(scene->GetTextureTable());
        chartAggregator->SetTexCoordLevel(0);
        chartAggregator->SetTextureWidth(1024);
        chartAggregator->SetTextureHeight(1024);
        chartAggregator->SetGutterSpace(4);
        spWavefrontExporter objExporter = sg->CreateWavefrontExporter();
    
    
        // Unweighted layout (i.e. all charts are scaled with the same factor, so sizes correspond to the proportions defined by their old UVs)
        //
        spGeometryData workingGeometry = originalGeometry->NewCopy(true);
    
        chartAggregator->SetChartAggregatorMode(SG_CHARTAGGREGATORMODE_UVSIZEPROPORTIONS);
        chartAggregator->Parameterize(workingGeometry, workingGeometry->GetTexCoords(0));
    
        sceneMesh->SetGeometry(workingGeometry);
        objExporter->SetExportFilePath(output_unweighted_filename.c_str());
        objExporter->SetScene(scene);
        objExporter->RunExport();
    
    
        // Chart size based on corresponding geometry area in 3D-space, i.e. pixel density per area will be consistent across the mesh
        //
        workingGeometry = originalGeometry->NewCopy(true);
    
        chartAggregator->SetChartAggregatorMode(SG_CHARTAGGREGATORMODE_SURFACEAREA);
        chartAggregator->Parameterize(workingGeometry, workingGeometry->GetTexCoords(0));
    
        sceneMesh->SetGeometry(workingGeometry);
        objExporter = sg->CreateWavefrontExporter();
        objExporter->SetExportFilePath(output_areaweighted_filename.c_str());
        objExporter->SetScene(scene);
        objExporter->RunExport();
    
        // Chart size based on the original texture sizes. Here we want the output chart proportions to be determined by the original textures proportions
        //
        workingGeometry = originalGeometry->NewCopy(true);
    
        chartAggregator->SetChartAggregatorMode(SG_CHARTAGGREGATORMODE_TEXTURESIZEPROPORTIONS);
    
        // We can decide which texture channel decides which proportions to keep, diffuse if default
        //chartAggregator->SetOriginalChartProportionsChannel(SG_MATERIAL_CHANNEL_DIFFUSE);
    
        chartAggregator->Parameterize(workingGeometry, workingGeometry->GetTexCoords(0));
    
        sceneMesh->SetGeometry(workingGeometry);
        objExporter = sg->CreateWavefrontExporter();
        objExporter->SetExportFilePath(output_textureweighted_filename.c_str());
        objExporter->SetScene(scene);
        objExporter->RunExport();
    
        // Chart size based on the original texture sizes, while perfectly maintaining the pixel density of the original textures. Will override manually set output texture sizes.
        //
        workingGeometry = originalGeometry->NewCopy(true);
    
        chartAggregator->SetChartAggregatorMode(SG_CHARTAGGREGATORMODE_ORIGINALPIXELDENSITY);
    
        // We can decide which texture channel decides which proportions to keep, diffuse if default
        //chartAggregator->SetOriginalChartProportionsChannel(SG_MATERIAL_CHANNEL_DIFFUSE);
    
        chartAggregator->Parameterize(workingGeometry, workingGeometry->GetTexCoords(0));
    
        sceneMesh->SetGeometry(workingGeometry);
        objExporter = sg->CreateWavefrontExporter();
        objExporter->SetExportFilePath(output_preservedpixeldensity_filename.c_str());
        objExporter->SetScene(scene);
        objExporter->RunExport();
    
    }
    
    Back to top Terms of Use | Privacy and cookies | Trademarks | Copyright © 2019 Microsoft