This example shows how to use the Billboard cloud vegetation pipeline

// Copyright (c) Microsoft Corporation. 
// Licensed under the MIT license. 

#include <string>
#include <stdlib.h>
#include <filesystem>
#include <future>
#include "SimplygonLoader.h"


void RunBillboardCloudVegetationPipeline(Simplygon::ISimplygon* sg)
{
	Simplygon::spSceneImporter sgSceneImporter = sg->CreateSceneImporter();
	sgSceneImporter->SetImportFilePath( "../Assets/Tree/Tree.obj" );
	if(!sgSceneImporter->RunImport())
		throw std::exception("Failed to load Tree/Tree.obj.");
	Simplygon::spScene sgScene = sgSceneImporter->GetScene();

	// For all materials in the scene set the blend mode to blend (instead of opaque) 
	int materialCount = (int)sgScene->GetMaterialTable()->GetMaterialsCount();
	for (int i = 0; i < materialCount; ++i)
	{
		sgScene->GetMaterialTable()->GetMaterial(i)->SetBlendMode(Simplygon::EMaterialBlendMode::Blend);
	}

	// Create the Impostor processor. 
	Simplygon::spBillboardCloudVegetationPipeline sgBillboardCloudVegetationPipeline = sg->CreateBillboardCloudVegetationPipeline();

	Simplygon::spBillboardCloudSettings sgBillboardCloudSettings = sgBillboardCloudVegetationPipeline->GetBillboardCloudSettings();
	Simplygon::spMappingImageSettings sgMappingImageSettings = sgBillboardCloudVegetationPipeline->GetMappingImageSettings();

	// Set billboard cloud mode to Foliage. 
	sgBillboardCloudSettings->SetBillboardMode( Simplygon::EBillboardMode::Foliage );
	sgBillboardCloudSettings->SetBillboardDensity( 0.5f );
	sgBillboardCloudSettings->SetGeometricComplexity( 0.9f );
	sgBillboardCloudSettings->SetMaxPlaneCount( 10 );
	sgBillboardCloudSettings->SetTwoSided( true );

	Simplygon::spFoliageSettings sgFoliageSettings = sgBillboardCloudSettings->GetFoliageSettings();

	// Set the parameters for separating foliage and trunk. 
	sgFoliageSettings->SetSeparateTrunkAndFoliage( true );
	sgFoliageSettings->SetSeparateFoliageTriangleRatio( 0.5f );
	sgFoliageSettings->SetSeparateFoliageTriangleThreshold( 10 );
	sgFoliageSettings->SetSeparateFoliageAreaThreshold( 0.1f );
	sgFoliageSettings->SetSeparateFoliageSizeThreshold( 0.1f );
	sgFoliageSettings->SetTrunkReductionRatio( 0.5f );

	sgMappingImageSettings->SetMaximumLayers( 10 );

	Simplygon::spMappingImageOutputMaterialSettings sgOutputMaterialSettings = sgMappingImageSettings->GetOutputMaterialSettings(0);

	// Setting the size of the output material for the mapping image. This will be the output size of the 
	// textures when we do material casting in a later stage. 
	sgOutputMaterialSettings->SetTextureWidth( 1024 );
	sgOutputMaterialSettings->SetTextureHeight( 1024 );
	sgOutputMaterialSettings->SetMultisamplingLevel( 2 );

	// Add diffuse material caster to pipeline. 
	Simplygon::spColorCaster sgDiffuseCaster = sg->CreateColorCaster();

	Simplygon::spColorCasterSettings sgDiffuseCasterSettings = sgDiffuseCaster->GetColorCasterSettings();
	sgDiffuseCasterSettings->SetMaterialChannel( "Diffuse" );
	sgDiffuseCasterSettings->SetOutputImageFileFormat( Simplygon::EImageOutputFormat::PNG );
	sgDiffuseCasterSettings->SetBakeOpacityInAlpha( false );
	sgDiffuseCasterSettings->SetOutputPixelFormat( Simplygon::EPixelFormat::R8G8B8 );
	sgDiffuseCasterSettings->SetDilation( 10 );
	sgDiffuseCasterSettings->SetFillMode( Simplygon::EAtlasFillMode::Interpolate );

	sgBillboardCloudVegetationPipeline->AddMaterialCaster( sgDiffuseCaster, 0 );

	// Add specular material caster to pipeline. 
	Simplygon::spColorCaster sgSpecularCaster = sg->CreateColorCaster();

	Simplygon::spColorCasterSettings sgSpecularCasterSettings = sgSpecularCaster->GetColorCasterSettings();
	sgSpecularCasterSettings->SetMaterialChannel( "Specular" );
	sgSpecularCasterSettings->SetOutputImageFileFormat( Simplygon::EImageOutputFormat::PNG );
	sgSpecularCasterSettings->SetDilation( 10 );
	sgSpecularCasterSettings->SetFillMode( Simplygon::EAtlasFillMode::Interpolate );

	sgBillboardCloudVegetationPipeline->AddMaterialCaster( sgSpecularCaster, 0 );

	// Add normals material caster to pipeline. 
	Simplygon::spNormalCaster sgNormalsCaster = sg->CreateNormalCaster();

	Simplygon::spNormalCasterSettings sgNormalsCasterSettings = sgNormalsCaster->GetNormalCasterSettings();
	sgNormalsCasterSettings->SetMaterialChannel( "Normals" );
	sgNormalsCasterSettings->SetGenerateTangentSpaceNormals( true );
	sgNormalsCasterSettings->SetOutputImageFileFormat( Simplygon::EImageOutputFormat::PNG );
	sgNormalsCasterSettings->SetDilation( 10 );
	sgNormalsCasterSettings->SetFillMode( Simplygon::EAtlasFillMode::Interpolate );

	sgBillboardCloudVegetationPipeline->AddMaterialCaster( sgNormalsCaster, 0 );

	// Setup and run the opacity material casting. Make sure the there is no dilation or fill. 
	Simplygon::spOpacityCaster sgOpacityCaster = sg->CreateOpacityCaster();

	Simplygon::spOpacityCasterSettings sgOpacityCasterSettings = sgOpacityCaster->GetOpacityCasterSettings();
	sgOpacityCasterSettings->SetMaterialChannel( "Opacity" );
	sgOpacityCasterSettings->SetOutputImageFileFormat( Simplygon::EImageOutputFormat::PNG );
	sgOpacityCasterSettings->SetFillMode( Simplygon::EAtlasFillMode::NoFill );
	sgOpacityCasterSettings->SetOutputPixelFormat( Simplygon::EPixelFormat::R8 );

	sgBillboardCloudVegetationPipeline->AddMaterialCaster( sgOpacityCaster, 0 );

	// Start the impostor pipeline. 
	sgBillboardCloudVegetationPipeline->RunScene(sgScene, Simplygon::EPipelineRunMode::RunInThisProcess);

	// Get the processed scene. 
	Simplygon::spScene sgProcessedScene = sgBillboardCloudVegetationPipeline->GetProcessedScene();

	Simplygon::spSceneExporter  sgSceneExporter = sg->CreateSceneExporter();
	sgSceneExporter->SetScene(sgProcessedScene);
	sgSceneExporter->SetExportFilePath( "FoliageOutput.obj" );
	if(!sgSceneExporter->RunExport())
		throw std::exception("Failed to save FoliageOutput.obj.");

}

int main()
{
	Simplygon::ISimplygon* sg = NULL;
	Simplygon::EErrorCodes initval = Simplygon::Initialize( &sg );
	if( initval != Simplygon::EErrorCodes::NoError )
	{
		return int(initval);
	}

	RunBillboardCloudVegetationPipeline(sg);

	Simplygon::Deinitialize(sg);

	return 0;
}