AggregationProcessorExample.cpp

<< Click to Display Table of Contents >>

Navigation:  Simplygon 7.1 examples >

AggregationProcessorExample.cpp

///////////////////////////////////////////////////////////////////////////
//
//  System:    Simplygon
//  File:      AggregationProcessorExample.cpp
//  Language:  C++
//
//  Copyright (c) 2015 Donya Labs AB. 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#
//
//  Reduce drawcalls by using the IAggregationProcessor to combine all the
//  objects in a scene into a single new object that shares newly
//  generated textures.
//
//
//  A scene with multiple objects and materials is loaded.
//  The scene contains 4 instances of the SimplygonMan,
//  1 textured Utah teapot and 1 textured plane.
//
//  We run an AggregationProcessor on the scene and export the result as a
//  Wavefront file.
//
//  The resulting scene has a single texture per material channel (diffuse
//  and specular). All textures have been combined into these new textures.
//  All texture coordinates have been re-computed to map to the new
//  textures.
//
//  The 4 SimplygonMan meshes share texture coordinates since they had
//  the same textures. The plane and Utah teapot have new unique
//  UV-coordinates.
//
//  See the output texture images to see how the textures have been
//  combined.
//
///////////////////////////////////////////////////////////////////////////
#include "../Common/Example.h"
class ProgressObserver : public robserver
    {
    public :
        virtual void Execute (
            IObject * subject ,
            rid EventId ,
            void * EventParameterBlock ,
            unsigned int EventParameterBlockSize )
            {
            // only care for progress events
            if( EventId == SG_EVENT_PROGRESS )
                {
                // get the progress in percent
                int val = *(( int *) EventParameterBlock );
                // tell the process to continue
                // this is required by the progress event
                *(( int *) EventParameterBlock ) = 1;
                // output the progress update
                PrintProgressBar(val);
                }
            }
    } progressObserver;
void RunExample(const std::string& readFrom, const std::string& writeTo);
int main( int argc , char* argv[] )
    {
    InitExample();
    // Set global variable. Using Orthonormal method for calculating
    // tangentspace.
    sg->SetGlobalSetting( "DefaultTBNType" , SG_TANGENTSPACEMETHOD_ORTHONORMAL );
    std::string assetPath = GetAssetPath();
    // Run
    printf("Running scene aggregation...\n");
    PrintProgressBar(0); //Initial progress bar
    RunExample( assetPath + "CombineScene/scene.obj", "CombinedScene_out" );
    printf("\nDone.\n\n");
    printf("All LODs complete, shutting down...");
    DeinitExample();
    return 0;
    }
void RunExample(const std::string& readFrom, const std::string& writeTo)
    {
    // Load from file
    spWavefrontImporter objReader = sg->CreateWavefrontImporter();
    objReader->SetImportFilePath( readFrom.c_str() );
    if( !objReader->RunImport() )
        return;
    // Get the scene
    spScene scene = objReader->GetScene();
    // Create the spAggregationProcessor
    spAggregationProcessor aggregationProcessor = sg->CreateAggregationProcessor();
    // Set the input scene
    aggregationProcessor->SetScene(scene);
    spAggregationSettings aggregatorSettings = aggregationProcessor->GetAggregationSettings();
    // 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(1);
    mappingImageSettings->SetWidth(2048);
    mappingImageSettings->SetHeight(2048);
    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);
    //Add observer
    aggregationProcessor->AddObserver(&progressObserver, SG_EVENT_PROGRESS);
    // Run the process
    aggregationProcessor->RunProcessing();
    //Create a new material that we cast the new textures onto
    spMaterial outputMaterial = sg->CreateMaterial();
    outputMaterial->SetName( "output_material" );
    spMaterialTable outputMaterialTable = sg->CreateMaterialTable();
    outputMaterialTable->AddMaterial(outputMaterial);
    outputMaterialTable->SetName("CombinedMaterials");
    spColorCaster diffuseCaster = sg->CreateColorCaster();
    diffuseCaster->SetColorType( SG_MATERIAL_CHANNEL_DIFFUSE );
    diffuseCaster->SetSourceMaterials( scene->GetMaterialTable() );
    diffuseCaster->SetOutputFilePath( "outputDiffuse.png" );
    diffuseCaster->SetMappingImage( aggregationProcessor->GetMappingImage() );
    diffuseCaster->CastMaterials();
    outputMaterial->SetColor(SG_MATERIAL_CHANNEL_DIFFUSE, 1.0,1.0,1.0,1.0);
    // Set material to point to created texture filename.
    outputMaterial->SetTexture( SG_MATERIAL_CHANNEL_DIFFUSE , "outputDiffuse.png" );
    spColorCaster specularCaster = sg->CreateColorCaster();
    specularCaster->SetColorType( SG_MATERIAL_CHANNEL_SPECULAR );
    specularCaster->SetSourceMaterials( scene->GetMaterialTable() );
    specularCaster->SetOutputFilePath( "outputSpecular.png" );
    specularCaster->SetMappingImage( aggregationProcessor->GetMappingImage() );
    specularCaster->CastMaterials();
    outputMaterial->SetColor(SG_MATERIAL_CHANNEL_SPECULAR, 1.0,1.0,1.0,1.0);
    // Set material to point to created texture filename.
    outputMaterial->SetTexture( SG_MATERIAL_CHANNEL_SPECULAR, "outputSpecular.png" );
    scene->GetMaterialTable()->Copy(outputMaterialTable);
    // Store to file
    spWavefrontExporter objexp = sg->CreateWavefrontExporter();
    std::string output_geometry_filename = GetExecutablePath() + writeTo + ".obj";
    objexp->SetExportFilePath( output_geometry_filename.c_str() );
    spGeometryData geometry = ISceneMesh::SafeCast( scene->GetRootNode()->GetChild(0) )->GetGeometry();
    //Sets all triangle's material IDs to the single new material
    for(uint i = 0 ; i < geometry->GetTriangleCount() ; ++i )
        {
        geometry->GetMaterialIds()->SetItem(i, 0);
        }
    objexp->SetScene(scene);
    objexp->RunExport();
    }