Pipelines
Simplygon pipelines combines common processing patterns into easy to use pipelines. This allows you to cover most of the normal workflows with predefined API entrypoints without having to setup each individual processing object manually. It also allows for distribution by serializing the pipeline definition to a file and executing the pipeline on a remote node using the pipeline batch executable.
Reduction pipeline (IReductionPipeline)
Geometries are reduced using the reduction processor and optionally new materials are baked using material casters.Remeshing pipeline (IRemeshingPipeline)
Geometries are replaced using the remeshing processor and optionally new materials are baked using material casters.Aggregation pipeline (IAggregationPipeline) Geometries are combined using the aggregation processor and optionally new materials are baked using material casters.
The processors and material casters are configured using the settings exposed.
Pipeline settings
Pipelines are configured using the settings exposed by the processors and casters in the corresponding pipeline. The settings are either accessed directly through the API objects, or indirectly through paths.
Settings objects
Settings can be manipulated using the API object directly:
spReductionPipeline reductionPipeline = sg->CreateReductionPipeline();
// Access the settings object for the reduction processor
spReductionSettings reductionSettings = reductionPipeline->GetReductionSettings();
// Set the value for a setting in the settings object
reductionSettings->SetUseHighQualityNormalCalculation( true );
// Get the value for a setting in the settings object
if( reductionSettings->GetUseHighQualityNormalCalculation() )
{
// ...
}
Settings paths
Paths can be used to set and get parameters directly on the pipeline object. The paths are created on the form {processor}/{settings_object}/{setting_name}
where
{processor}
is the name of the processor (RemeshingProcessor, ReductionProcessor, AggregationProcessor){settings_object}
is the name of the settings object to manipulate (like Reduction, Repair, MappingImage etc, matching the API callGet{settings_object}Settings()
on the processor){setting_name}
is the actual setting name.
The type must match the setting variable type as exposed in the setting object, so a Set{setting_name}( unsinged int )
function on the settings object taking an unsigned integer must be accessed with a SetUIntParameter( "{processor}/{settings_object}/setting_name" )
call. Using the wrong typed Set/Get function is an error. Example:
spReductionPipeline reductionPipeline = sg->CreateReductionPipeline();
// Set the value for a setting using the path
reductionPipeline->SetBoolParameter( "ReductionProcessor/Reduction/UseHighQualityNormalCalculation", true );
// Get the value for a setting using the path
if( reductionPipeline->GetBoolParameter( "ReductionProcessor/Reduction/UseHighQualityNormalCalculation" ) )
{
// ...
}
The path access is mostly indended for use in languages and environments where string manipulation is the canonical way of working. In native C++ we recommend using the settings API objects directly.
Generic pipeline settings
All pipelines have a generic settings object for shared settings across all pipelines. It is accessed through GetPipelineSettings()
on the pipeline object, or with the path Pipeline/{settings_name}
in the path API.
Global settings
The global settings for the Simplygon API can also be accessed through the path API, using the path Global/{settings_name}
.
Input and output
Pipelines take scenes as input and return processed scenes as output. Input and output can either be scene API objects, or paths to files that can be read as scenes. Currently the file formats supported are limited to the internal scene file format and Wavefront OBJ files. In the case of material casting, the resulting output textures are saved as PNG files in the directory set in TextureOutputPath
in the generic pipeline settings object. If the path is relative it is treated as relative to the current working directory.
Example using scene API objects
spReductionPipeline reductionPipeline = sg->CreateReductionPipeline();
sgScene scene = <your code to create/setup scene>;
// The scene passed in is modified by the pipeline and geometries and materials are modified and/or replaced
reductionPipeline->RunScene( scene );
Example using file paths
spReductionPipeline reductionPipeline = sg->CreateReductionPipeline();
// The scene file passed in is NOT modified by the pipeline, the modified scene is written to the output path
// Wavefront OBJ files
reductionPipeline->RunSceneFromFile( "path/to/input/scene.obj", "path/to/output/scene.obj" );
// Internal scene file format
reductionPipeline->RunSceneFromFile( "path/to/input/scene.sg", "path/to/output/scene.sg" );
Material casters
Pipelines allow material casting by attaching any number of material casters to the pipeline. The material casters will execute after the processor in the pipeline and bake the configured texture channels. Materials on scene geometry will be replaced by the new baked materials using the cast textures. Any number of output materials can be baked, and the material index given to AddMaterialCaster
determines which material the caster will output texture to.
The pipeline must be configured to use mapping images if you want material casting. This is done with SetGenerateMappingImage(true)
on the pipeline mapping image settings.
Example:
spReductionPipeline reductionPipeline = sg->CreateReductionPipeline();
spColorCaster diffuseCaster = sg->CreateColorCaster();
reductionPipeline->AddMaterialCaster( diffuseCaster, 0 );
There is also a string based interface to add material casters to a pipeline:
spReductionPipeline reductionPipeline = sg->CreateReductionPipeline();
spMaterialCaster materialCaster = reductionPipeline->AddMaterialCasterByType( "Color", 0 );
The caster type is the base type name without leading interface identifier and caster suffix, i.e IColorCaster
becomes Color
, INormalCaster
becomes Normal
.
Material caster settings
You can access the caster settings through the caster object API, for example IColorCaster::GetColorCasterSettings()
.
To access the caster settings through the string based path API you use a zero based index in the path to specify which caster to access, for example "MaterialCaster/0/MaterialChannel" to specify the name of the first caster material output channel.
Example - Reduction pipeline
The following example shows how to use the reduction pipeline
//Create a reduction pipeline
spReductionPipeline reductionPipeline = sg->CreateReductionPipeline();
///////////////////////////////////////////////////////////////////////////////////////////////
// SETTINGS - Most of these are set to the same value by default, but are set anyway for clarity
spPipelineSettings pipelineSettings = reductionPipeline->GetPipelineSettings();
pipelineSettings->SetTextureOutputPath( "Textures" );
// The reduction settings object contains settings pertaining to the actual decimation
spReductionSettings reductionSettings = reductionPipeline->GetReductionSettings();
reductionSettings->SetReductionHeuristics( SG_REDUCTIONHEURISTICS_FAST );
reductionSettings->SetStopCondition( SG_STOPCONDITION_ANY );
reductionSettings->SetReductionTargets( SG_REDUCTIONTARGET_ALL );
reductionSettings->SetTriangleRatio( 0.5 ); //Targets at 50% of the original triangle count
reductionSettings->SetTriangleCount( 10 ); //Targets when only 10 triangle remains
reductionSettings->SetMaxDeviation( REAL_MAX ); //Targets when an error of the specified size has been reached. As set here it never happens.
reductionSettings->SetOnScreenSize( 50 ); //Targets when the LOD is optimized for the selected on screen pixel size
// The normal calculation settings deal with the normal-specific reduction settings
spNormalCalculationSettings normalSettings = reductionPipeline->GetNormalCalculationSettings();
normalSettings->SetReplaceNormals( true );
normalSettings->SetHardEdgeAngleInRadians( 3.14f );
// The Image Mapping Settings, specifically needed for the texture baking we are doing later
spMappingImageSettings mappingSettings = reductionPipeline->GetMappingImageSettings();
mappingSettings->SetUseFullRetexturing( false );
mappingSettings->SetGenerateMappingImage( true ); //Required for material casting
mappingSettings->SetGenerateTexCoords( true );
mappingSettings->SetGenerateTangents( true );
mappingSettings->SetTexCoordLevelName( "reduced" ); //Set texcoord level name to generate a new UV set and keep the old instead of overwriting level 0
mappingSettings->SetParameterizerMaxStretch( 0.8f );
mappingSettings->SetGutterSpace( 2 );
mappingSettings->SetTexCoordLevel( 0 );
mappingSettings->SetWidth( 1024 );
mappingSettings->SetHeight( 1024 );
mappingSettings->SetMultisamplingLevel( 2 );
// Cast diffuse and specular texture data with a color caster
spColorCaster diffuseCaster = sg->CreateColorCaster();
spColorCasterSettings diffuseCasterSettings = diffuseCaster->GetColorCasterSettings();
diffuseCasterSettings->SetOutputChannelBitDepth( 8 );
diffuseCasterSettings->SetDilation( 10 );
diffuseCasterSettings->SetOutputChannels( 3 );
diffuseCasterSettings->SetMaterialChannel( SG_MATERIAL_CHANNEL_DIFFUSE );
spColorCaster specularCaster = sg->CreateColorCaster();
spColorCasterSettings specularCasterSettings = specularCaster->GetColorCasterSettings();
specularCasterSettings->SetOutputChannelBitDepth( 8 );
specularCasterSettings->SetDilation( 10 );
specularCasterSettings->SetOutputChannels( 4 );
specularCasterSettings->SetMaterialChannel( SG_MATERIAL_CHANNEL_SPECULAR );
// Cast normal map texture data with the normal caster. This also compensates for any geometric errors that have appeared in the reduction process.
spNormalCaster normalCaster = sg->CreateNormalCaster();
spNormalCasterSettings normalCasterSettings = normalCaster->GetNormalCasterSettings();
normalCasterSettings->SetOutputChannels( 3 );
normalCasterSettings->SetOutputChannelBitDepth( 8 );
normalCasterSettings->SetDilation( 10 );
normalCasterSettings->SetFlipBackfacingNormals( false );
normalCasterSettings->SetGenerateTangentSpaceNormals( true );
normalCasterSettings->SetMaterialChannel( SG_MATERIAL_CHANNEL_NORMALS );
reductionPipeline->AddMaterialCaster( diffuseCaster, 0 );
reductionPipeline->AddMaterialCaster( specularCaster, 0 );
reductionPipeline->AddMaterialCaster( normalCaster, 0 );
//END SETTINGS
///////////////////////////////////////////////////////////////////////////////////////////////
// Add progress observer
reductionPipeline->AddObserver( &progressObserver, SG_EVENT_PROGRESS );
// Run the actual processing. After this, the set geometry will have been reduced according to the settings
// and materials will have been baked, generating new textures in the directory specified in settings above
reductionPipeline->RunSceneFromFile( "input.obj", "output.obj" );
Event handling
The pipelines supports the progress event, SG_EVENT_PROGRESS, and aggregate progress events from the processors and casters into a single continuous range. For details regarding event handling, see the section on event handling.
Example
// Progress observer class that prints progress to stdout.
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.
printf( "Progress: %d%%\n", val );
}
}
} progressObserverObject;
void RegisterEventObserver( spReductionPipeline pipeline )
{
// Register the event observer class with the pipeline.
// Tell it we want progress events only.
pipeline->AddObserver( &progressObserverObject, SG_EVENT_PROGRESS );
}
Batch processing
Pipelines can be serialized for batch processing and/or distribution by use of the batch executable tool.
Serializing a pipeline
Pipelines are serialized using the IPipelineSerializer
interface.
sgPipelineSerializer serializer = sg->CreatePipelineSerializer();
// Save a pipeline
sgPipeline pipeline = <your code to configure pipeline>;
serializer->SavePipelineToFile( "path/to/pipeline.json", pipeline);
// Load a pipeline
sgPipeline pipeline = serializer->LoadPipelineFromFile( "path/to/pipeline.json" );
Executing a pipeline using batch tool
Run the batch tool executable with three arguments specifying serialized pipeline file, input scene file and output scene file. Created textures are output according to the texture output path settings set in the pipeline.
SimplygonBatch.exe <path/to/pipeline.json> <path/to/input.obj> <path/to/output.obj>
Progress reporting
If you want to parse the progress of the pipeline you can pass -Progress
as an extra first parameter to the batch tool executable. This will supress any output from the pipeline execution and instead print progress on stdout as a integer percentage number in [0,100] range separated by newlines. The calling executable can then read stdin and parse the output as integers, one per line.
SimplygonBatch.exe -Progress <path/to/pipeline.json> <path/to/input.obj> <path/to/output.obj>