<< 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();
}