# Distribution
If you don't want to run the Simplygon processing on your local machine you can use distribution to offload the work to another machine. Simplygon support three different distribution methods (Simplygon Grid, Incredibuild and FASTBuild) and you can use distribution in our integrations or directly in the Simplygon API.
Please see Pipeline distribution for more information.
This example shows how to do batch processing using Simplygon Grid.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#include <string>
#include <stdlib.h>
#include <filesystem>
#include <future>
#include "SimplygonLoader.h"
void CheckLog(Simplygon::ISimplygon* sg)
{
// Check if any errors occurred.
bool hasErrors = sg->ErrorOccurred();
if (hasErrors)
{
Simplygon::spStringArray errors = sg->CreateStringArray();
sg->GetErrorMessages(errors);
auto errorCount = errors->GetItemCount();
if (errorCount > 0)
{
printf("%s\n", "Errors:");
for (auto errorIndex = 0U; errorIndex < errorCount; ++errorIndex)
{
Simplygon::spString errorString = errors->GetItem((int)errorIndex);
printf("%s\n", errorString.c_str());
}
sg->ClearErrorMessages();
}
}
else
{
printf("%s\n", "No errors.");
}
// Check if any warnings occurred.
bool hasWarnings = sg->WarningOccurred();
if (hasWarnings)
{
Simplygon::spStringArray warnings = sg->CreateStringArray();
sg->GetWarningMessages(warnings);
auto warningCount = warnings->GetItemCount();
if (warningCount > 0)
{
printf("%s\n", "Warnings:");
for (auto warningIndex = 0U; warningIndex < warningCount; ++warningIndex)
{
Simplygon::spString warningString = warnings->GetItem((int)warningIndex);
printf("%s\n", warningString.c_str());
}
sg->ClearWarningMessages();
}
}
else
{
printf("%s\n", "No warnings.");
}
}
void RunReduction(Simplygon::ISimplygon* sg, std::string inputFile, std::string outputFile)
{
// Create the reduction pipeline.
Simplygon::spReductionPipeline sgReductionPipeline = sg->CreateReductionPipeline();
Simplygon::spReductionSettings sgReductionSettings = sgReductionPipeline->GetReductionSettings();
// Set reduction target to triangle ratio with a ratio of 50%.
sgReductionSettings->SetReductionTargets( Simplygon::EStopCondition::All, true, false, false, false );
sgReductionSettings->SetReductionTargetTriangleRatio( 0.5f );
// Start the reduction pipeline.
printf("%s\n", "Start the reduction pipeline.");
sgReductionPipeline->RunSceneFromFile(inputFile.c_str(), outputFile.c_str(), Simplygon::EPipelineRunMode::RunDistributedUsingSimplygonGrid);
// Check log for any warnings or errors.
printf("%s\n", "Check log for any warnings or errors.");
CheckLog(sg);
}
int main()
{
Simplygon::ISimplygon* sg = NULL;
Simplygon::EErrorCodes initval = Simplygon::Initialize( &sg );
if( initval != Simplygon::EErrorCodes::NoError )
{
printf( "Failed to initialize Simplygon: ErrorCode(%d)", (int)initval );
return int(initval);
}
std::vector<std::future<void>> jobs;
for(auto& itr: std::filesystem::recursive_directory_iterator("../../../Assets/"))
{
if (itr.path().extension().compare(".glb") != 0)
continue;
std::string inputFile = itr.path().generic_u8string();
std::string outputFile = itr.path().stem().concat("_LOD").concat( itr.path().extension().generic_u8string() ).generic_u8string();
jobs.push_back( std::async( [](Simplygon::ISimplygon * sg, std::string inputFile, std::string outputFile)
{
RunReduction(sg, inputFile, outputFile);
}, sg, inputFile, outputFile ));
}
for(auto& job: jobs)
{
job.wait();
}
Simplygon::Deinitialize(sg);
return 0;
}
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using System;
using System.IO;
using System.Threading.Tasks;
public class Program
{
static void CheckLog(Simplygon.ISimplygon sg)
{
// Check if any errors occurred.
bool hasErrors = sg.ErrorOccurred();
if (hasErrors)
{
Simplygon.spStringArray errors = sg.CreateStringArray();
sg.GetErrorMessages(errors);
var errorCount = errors.GetItemCount();
if (errorCount > 0)
{
Console.WriteLine("Errors:");
for (uint errorIndex = 0; errorIndex < errorCount; ++errorIndex)
{
string errorString = errors.GetItem((int)errorIndex);
Console.WriteLine(errorString);
}
sg.ClearErrorMessages();
}
}
else
{
Console.WriteLine("No errors.");
}
// Check if any warnings occurred.
bool hasWarnings = sg.WarningOccurred();
if (hasWarnings)
{
Simplygon.spStringArray warnings = sg.CreateStringArray();
sg.GetWarningMessages(warnings);
var warningCount = warnings.GetItemCount();
if (warningCount > 0)
{
Console.WriteLine("Warnings:");
for (uint warningIndex = 0; warningIndex < warningCount; ++warningIndex)
{
string warningString = warnings.GetItem((int)warningIndex);
Console.WriteLine(warningString);
}
sg.ClearWarningMessages();
}
}
else
{
Console.WriteLine("No warnings.");
}
}
static void RunReduction(Simplygon.ISimplygon sg, string inputFile, string outputFile)
{
// Create the reduction pipeline.
using Simplygon.spReductionPipeline sgReductionPipeline = sg.CreateReductionPipeline();
using Simplygon.spReductionSettings sgReductionSettings = sgReductionPipeline.GetReductionSettings();
// Set reduction target to triangle ratio with a ratio of 50%.
sgReductionSettings.SetReductionTargets( Simplygon.EStopCondition.All, true, false, false, false );
sgReductionSettings.SetReductionTargetTriangleRatio( 0.5f );
// Start the reduction pipeline.
Console.WriteLine("Start the reduction pipeline.");
sgReductionPipeline.RunSceneFromFile(inputFile, outputFile, Simplygon.EPipelineRunMode.RunDistributedUsingSimplygonGrid);
// Check log for any warnings or errors.
Console.WriteLine("Check log for any warnings or errors.");
CheckLog(sg);
}
static int Main(string[] args)
{
using var sg = Simplygon.Loader.InitSimplygon(out var errorCode, out var errorMessage);
if (errorCode != Simplygon.EErrorCodes.NoError)
{
Console.WriteLine( $"Failed to initialize Simplygon: ErrorCode({(int)errorCode}) {errorMessage}" );
return (int)errorCode;
}
var inputFiles = Directory.EnumerateFiles("../../../Assets/", "*.glb", SearchOption.AllDirectories);
Parallel.ForEach(inputFiles, (inputFile) =>
{
string outputFile = Path.Combine(Path.GetFileNameWithoutExtension(inputFile) + "_LOD" + Path.GetExtension(inputFile));
RunReduction(sg, inputFile, outputFile);
});
return 0;
}
}
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
import math
import os
import sys
import glob
import gc
import threading
from pathlib import Path
from simplygon import simplygon_loader
from simplygon import Simplygon
def CheckLog(sg: Simplygon.ISimplygon):
# Check if any errors occurred.
hasErrors = sg.ErrorOccurred()
if hasErrors:
errors = sg.CreateStringArray()
sg.GetErrorMessages(errors)
errorCount = errors.GetItemCount()
if errorCount > 0:
print("Errors:")
for errorIndex in range(errorCount):
errorString = errors.GetItem(errorIndex)
print(errorString)
sg.ClearErrorMessages()
else:
print("No errors.")
# Check if any warnings occurred.
hasWarnings = sg.WarningOccurred()
if hasWarnings:
warnings = sg.CreateStringArray()
sg.GetWarningMessages(warnings)
warningCount = warnings.GetItemCount()
if warningCount > 0:
print("Warnings:")
for warningIndex in range(warningCount):
warningString = warnings.GetItem(warningIndex)
print(warningString)
sg.ClearWarningMessages()
else:
print("No warnings.")
def RunReduction(sg: Simplygon.ISimplygon, inputFile, outputFile):
# Create the reduction pipeline.
sgReductionPipeline = sg.CreateReductionPipeline()
sgReductionSettings = sgReductionPipeline.GetReductionSettings()
# Set reduction target to triangle ratio with a ratio of 50%.
sgReductionSettings.SetReductionTargets( Simplygon.EStopCondition_All, True, False, False, False )
sgReductionSettings.SetReductionTargetTriangleRatio( 0.5 )
# Start the reduction pipeline.
print("Start the reduction pipeline.")
sgReductionPipeline.RunSceneFromFile(inputFile, outputFile, Simplygon.EPipelineRunMode_RunDistributedUsingSimplygonGrid)
# Check log for any warnings or errors.
print("Check log for any warnings or errors.")
CheckLog(sg)
if __name__ == '__main__':
sg = simplygon_loader.init_simplygon()
if sg is None:
exit(Simplygon.GetLastInitializationError())
jobs = list()
inputFiles = glob.glob('../../../Assets/' + '/**/*.glb', recursive=True)
for inputFile in inputFiles:
outputFile = Path(inputFile).stem + '_LOD' + Path(inputFile).suffix
job = threading.Thread(target=RunReduction, args=(sg, inputFile, outputFile))
jobs.append(job)
job.start()
for job in jobs:
job.join()
sg = None
gc.collect()
← Blender File formats →