Skip to content
On this page

Visibility settings

Visibility can be computed for the scene or for a selected subset by using selection sets. This is done to determine which parts of the scene is actually visible. Scene cameras are added to the scene and the user can select which cameras should be used when calculating the visibility. Users can also provide an arbitrary geometry where the vertices are converted to cameras internally. If no cameras are selected, then a default set of cameras surrounding the scene will be used. The generated visibility weights can be used to guide the reduction, texcoord creation or used to simply remove all triangles that never are visible. For more details see Visibility Tool

Supported processors

  • Reduction processor
  • Remeshing processor
  • Aggregation processor

Camera example

This example shows how to use the Reduction processor with a visibility camera.

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

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


Simplygon::spScene LoadScene(Simplygon::ISimplygon* sg, const char* path)
{
	// Create scene importer 
	Simplygon::spSceneImporter sgSceneImporter = sg->CreateSceneImporter();
	sgSceneImporter->SetImportFilePath(path);
	
	// Run scene importer. 
	auto importResult = sgSceneImporter->Run();
	if (Simplygon::Failed(importResult))
	{
		throw std::exception("Failed to load scene.");
	}
	Simplygon::spScene sgScene = sgSceneImporter->GetScene();
	return sgScene;
}

void SaveScene(Simplygon::ISimplygon* sg, Simplygon::spScene sgScene, const char* path)
{
	// Create scene exporter. 
	Simplygon::spSceneExporter sgSceneExporter = sg->CreateSceneExporter();
	std::string outputScenePath = std::string("output\\") + std::string("ReductionWithVisibilityCamera") + std::string("_") + std::string(path);
	sgSceneExporter->SetExportFilePath(outputScenePath.c_str());
	sgSceneExporter->SetScene(sgScene);
	
	// Run scene exporter. 
	auto exportResult = sgSceneExporter->Run();
	if (Simplygon::Failed(exportResult))
	{
		throw std::exception("Failed to save scene.");
	}
}

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", "CheckLog: 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", "CheckLog: 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", "CheckLog: 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", "CheckLog: No warnings.");
	}
	
	// Error out if Simplygon has errors. 
	if (hasErrors)
	{
		throw std::exception("Processing failed with an error");
	}
}

void RunReduction(Simplygon::ISimplygon* sg)
{
	// Load scene to process. 	
	printf("%s\n", "Load scene to process.");
	Simplygon::spScene sgScene = LoadScene(sg, "../../../Assets/ObscuredTeapot/Teapot.obj");
	
	// Create the reduction processor. 
	Simplygon::spReductionProcessor sgReductionProcessor = sg->CreateReductionProcessor();
	sgReductionProcessor->SetScene( sgScene );
	Simplygon::spReductionSettings sgReductionSettings = sgReductionProcessor->GetReductionSettings();
	Simplygon::spVisibilitySettings sgVisibilitySettings = sgReductionProcessor->GetVisibilitySettings();
	
	// Set reduction target to triangle ratio with a ratio of 50%. 
	sgReductionSettings->SetReductionTargets( Simplygon::EStopCondition::All, true, false, false, false );
	sgReductionSettings->SetReductionTargetTriangleRatio( 0.5f );
	
	// Add a camera to the scene. We'll use this later as a visibility camera. 
	Simplygon::spSelectionSetTable sgSceneSelectionSetTable = sgScene->GetSelectionSetTable();
	Simplygon::spSelectionSet sgCameraSelectionSet = sg->CreateSelectionSet();
	sgCameraSelectionSet->SetName("Camera");
	Simplygon::spSceneCamera sgCameraSceneCamera = sg->CreateSceneCamera();
	sgCameraSceneCamera->SetCustomSphereCameraPath(4, 90, 180, 90);
	sgScene->GetRootNode()->AddChild(sgCameraSceneCamera);
	sgCameraSelectionSet->AddItem(sgCameraSceneCamera->GetNodeGUID());
	sgSceneSelectionSetTable->AddSelectionSet(sgCameraSelectionSet);
	
	// Use the camera previously added. 
	sgVisibilitySettings->SetCameraSelectionSetName( "Camera" );
	
	// Enabled GPU based visibility calculations. 
	sgVisibilitySettings->SetComputeVisibilityMode( Simplygon::EComputeVisibilityMode::DirectX );
	
	// Disabled conservative mode. 
	sgVisibilitySettings->SetConservativeMode( false );
	
	// Remove all non visible geometry. 
	sgVisibilitySettings->SetCullOccludedGeometry( true );
	
	// Skip filling nonvisible regions. 
	sgVisibilitySettings->SetFillNonVisibleAreaThreshold( 0.0f );
	
	// Don't remove non occluding triangles. 
	sgVisibilitySettings->SetRemoveTrianglesNotOccludingOtherTriangles( false );
	
	// Remove all back facing triangles. 
	sgVisibilitySettings->SetUseBackfaceCulling( true );
	
	// Don't use visibility weights. 
	sgVisibilitySettings->SetUseVisibilityWeightsInReducer( false );
	
	// Start the reduction process. 	
	printf("%s\n", "Start the reduction process.");
	sgReductionProcessor->RunProcessing();
	
	// Save processed scene. 	
	printf("%s\n", "Save processed scene.");
	SaveScene(sg, sgScene, "Output.fbx");
	
	// 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);
	}

	RunReduction(sg);

	Simplygon::Deinitialize(sg);

	return 0;
}
csharp
// Copyright (c) Microsoft Corporation. 
// Licensed under the MIT License. 

using System;
using System.IO;
using System.Threading.Tasks;

public class Program
{
    static Simplygon.spScene LoadScene(Simplygon.ISimplygon sg, string path)
    {
        // Create scene importer 
        using Simplygon.spSceneImporter sgSceneImporter = sg.CreateSceneImporter();
        sgSceneImporter.SetImportFilePath(path);
        
        // Run scene importer. 
        var importResult = sgSceneImporter.Run();
        if (Simplygon.Simplygon.Failed(importResult))
        {
            throw new System.Exception("Failed to load scene.");
        }
        Simplygon.spScene sgScene = sgSceneImporter.GetScene();
        return sgScene;
    }

    static void SaveScene(Simplygon.ISimplygon sg, Simplygon.spScene sgScene, string path)
    {
        // Create scene exporter. 
        using Simplygon.spSceneExporter sgSceneExporter = sg.CreateSceneExporter();
        string outputScenePath = string.Join("", new string[] { "output\\", "ReductionWithVisibilityCamera", "_", path });
        sgSceneExporter.SetExportFilePath(outputScenePath);
        sgSceneExporter.SetScene(sgScene);
        
        // Run scene exporter. 
        var exportResult = sgSceneExporter.Run();
        if (Simplygon.Simplygon.Failed(exportResult))
        {
            throw new System.Exception("Failed to save scene.");
        }
    }

    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("CheckLog: Errors:");
                for (uint errorIndex = 0; errorIndex < errorCount; ++errorIndex)
                {
                    string errorString = errors.GetItem((int)errorIndex);
                    Console.WriteLine(errorString);
                }
                sg.ClearErrorMessages();
            }
        }
        else
        {
            Console.WriteLine("CheckLog: 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("CheckLog: Warnings:");
                for (uint warningIndex = 0; warningIndex < warningCount; ++warningIndex)
                {
                    string warningString = warnings.GetItem((int)warningIndex);
                    Console.WriteLine(warningString);
                }
                sg.ClearWarningMessages();
            }
        }
        else
        {
            Console.WriteLine("CheckLog: No warnings.");
        }
        
        // Error out if Simplygon has errors. 
        if (hasErrors)
        {
            throw new System.Exception("Processing failed with an error");
        }
    }

    static void RunReduction(Simplygon.ISimplygon sg)
    {
        // Load scene to process.         
        Console.WriteLine("Load scene to process.");
        Simplygon.spScene sgScene = LoadScene(sg, "../../../Assets/ObscuredTeapot/Teapot.obj");
        
        // Create the reduction processor. 
        using Simplygon.spReductionProcessor sgReductionProcessor = sg.CreateReductionProcessor();
        sgReductionProcessor.SetScene( sgScene );
        using Simplygon.spReductionSettings sgReductionSettings = sgReductionProcessor.GetReductionSettings();
        using Simplygon.spVisibilitySettings sgVisibilitySettings = sgReductionProcessor.GetVisibilitySettings();
        
        // Set reduction target to triangle ratio with a ratio of 50%. 
        sgReductionSettings.SetReductionTargets( Simplygon.EStopCondition.All, true, false, false, false );
        sgReductionSettings.SetReductionTargetTriangleRatio( 0.5f );
        
        // Add a camera to the scene. We'll use this later as a visibility camera. 
        using Simplygon.spSelectionSetTable sgSceneSelectionSetTable = sgScene.GetSelectionSetTable();
        using Simplygon.spSelectionSet sgCameraSelectionSet = sg.CreateSelectionSet();
        sgCameraSelectionSet.SetName("Camera");
        using Simplygon.spSceneCamera sgCameraSceneCamera = sg.CreateSceneCamera();
        sgCameraSceneCamera.SetCustomSphereCameraPath(4, 90, 180, 90);
        sgScene.GetRootNode().AddChild(sgCameraSceneCamera);
        sgCameraSelectionSet.AddItem(sgCameraSceneCamera.GetNodeGUID());
        sgSceneSelectionSetTable.AddSelectionSet(sgCameraSelectionSet);
        
        // Use the camera previously added. 
        sgVisibilitySettings.SetCameraSelectionSetName( "Camera" );
        
        // Enabled GPU based visibility calculations. 
        sgVisibilitySettings.SetComputeVisibilityMode( Simplygon.EComputeVisibilityMode.DirectX );
        
        // Disabled conservative mode. 
        sgVisibilitySettings.SetConservativeMode( false );
        
        // Remove all non visible geometry. 
        sgVisibilitySettings.SetCullOccludedGeometry( true );
        
        // Skip filling nonvisible regions. 
        sgVisibilitySettings.SetFillNonVisibleAreaThreshold( 0.0f );
        
        // Don't remove non occluding triangles. 
        sgVisibilitySettings.SetRemoveTrianglesNotOccludingOtherTriangles( false );
        
        // Remove all back facing triangles. 
        sgVisibilitySettings.SetUseBackfaceCulling( true );
        
        // Don't use visibility weights. 
        sgVisibilitySettings.SetUseVisibilityWeightsInReducer( false );
        
        // Start the reduction process.         
        Console.WriteLine("Start the reduction process.");
        sgReductionProcessor.RunProcessing();
        
        // Save processed scene.         
        Console.WriteLine("Save processed scene.");
        SaveScene(sg, sgScene, "Output.fbx");
        
        // 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;
        }
        RunReduction(sg);

        return 0;
    }

}
python
# 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 simplygon10 import simplygon_loader
from simplygon10 import Simplygon


def LoadScene(sg: Simplygon.ISimplygon, path: str):
    # Create scene importer 
    sgSceneImporter = sg.CreateSceneImporter()
    sgSceneImporter.SetImportFilePath(path)
    
    # Run scene importer. 
    importResult = sgSceneImporter.Run()
    if Simplygon.Failed(importResult):
        raise Exception('Failed to load scene.')
    sgScene = sgSceneImporter.GetScene()
    return sgScene

def SaveScene(sg: Simplygon.ISimplygon, sgScene: Simplygon.spScene, path: str):
    # Create scene exporter. 
    sgSceneExporter = sg.CreateSceneExporter()
    outputScenePath = ''.join(['output\\', 'ReductionWithVisibilityCamera', '_', path])
    sgSceneExporter.SetExportFilePath(outputScenePath)
    sgSceneExporter.SetScene(sgScene)
    
    # Run scene exporter. 
    exportResult = sgSceneExporter.Run()
    if Simplygon.Failed(exportResult):
        raise Exception('Failed to save scene.')

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('CheckLog: Errors:')
            for errorIndex in range(errorCount):
                errorString = errors.GetItem(errorIndex)
                print(errorString)
            sg.ClearErrorMessages()
    else:
        print('CheckLog: 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('CheckLog: Warnings:')
            for warningIndex in range(warningCount):
                warningString = warnings.GetItem(warningIndex)
                print(warningString)
            sg.ClearWarningMessages()
    else:
        print('CheckLog: No warnings.')
    
    # Error out if Simplygon has errors. 
    if hasErrors:
        raise Exception('Processing failed with an error')

def RunReduction(sg: Simplygon.ISimplygon):
    # Load scene to process.     
    print("Load scene to process.")
    sgScene = LoadScene(sg, '../../../Assets/ObscuredTeapot/Teapot.obj')
    
    # Create the reduction processor. 
    sgReductionProcessor = sg.CreateReductionProcessor()
    sgReductionProcessor.SetScene( sgScene )
    sgReductionSettings = sgReductionProcessor.GetReductionSettings()
    sgVisibilitySettings = sgReductionProcessor.GetVisibilitySettings()
    
    # Set reduction target to triangle ratio with a ratio of 50%. 
    sgReductionSettings.SetReductionTargets( Simplygon.EStopCondition_All, True, False, False, False )
    sgReductionSettings.SetReductionTargetTriangleRatio( 0.5 )
    
    # Add a camera to the scene. We'll use this later as a visibility camera. 
    sgSceneSelectionSetTable = sgScene.GetSelectionSetTable()
    sgCameraSelectionSet = sg.CreateSelectionSet()
    sgCameraSelectionSet.SetName('Camera')
    sgCameraSceneCamera = sg.CreateSceneCamera()
    sgCameraSceneCamera.SetCustomSphereCameraPath(4, 90, 180, 90)
    sgScene.GetRootNode().AddChild(sgCameraSceneCamera)
    sgCameraSelectionSet.AddItem(sgCameraSceneCamera.GetNodeGUID())
    sgSceneSelectionSetTable.AddSelectionSet(sgCameraSelectionSet)
    
    # Use the camera previously added. 
    sgVisibilitySettings.SetCameraSelectionSetName( 'Camera' )
    
    # Enabled GPU based visibility calculations. 
    sgVisibilitySettings.SetComputeVisibilityMode( Simplygon.EComputeVisibilityMode_DirectX )
    
    # Disabled conservative mode. 
    sgVisibilitySettings.SetConservativeMode( False )
    
    # Remove all non visible geometry. 
    sgVisibilitySettings.SetCullOccludedGeometry( True )
    
    # Skip filling nonvisible regions. 
    sgVisibilitySettings.SetFillNonVisibleAreaThreshold( 0.0 )
    
    # Don't remove non occluding triangles. 
    sgVisibilitySettings.SetRemoveTrianglesNotOccludingOtherTriangles( False )
    
    # Remove all back facing triangles. 
    sgVisibilitySettings.SetUseBackfaceCulling( True )
    
    # Don't use visibility weights. 
    sgVisibilitySettings.SetUseVisibilityWeightsInReducer( False )
    
    # Start the reduction process.     
    print("Start the reduction process.")
    sgReductionProcessor.RunProcessing()
    
    # Save processed scene.     
    print("Save processed scene.")
    SaveScene(sg, sgScene, 'Output.fbx')
    
    # 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())

        RunReduction(sg)

        sg = None
        gc.collect()

Occluder example

This example shows how to use the Reduction processor with a visibility occluder.

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

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


Simplygon::spScene LoadScene(Simplygon::ISimplygon* sg, const char* path)
{
	// Create scene importer 
	Simplygon::spSceneImporter sgSceneImporter = sg->CreateSceneImporter();
	sgSceneImporter->SetImportFilePath(path);
	
	// Run scene importer. 
	auto importResult = sgSceneImporter->Run();
	if (Simplygon::Failed(importResult))
	{
		throw std::exception("Failed to load scene.");
	}
	Simplygon::spScene sgScene = sgSceneImporter->GetScene();
	return sgScene;
}

void SaveScene(Simplygon::ISimplygon* sg, Simplygon::spScene sgScene, const char* path)
{
	// Create scene exporter. 
	Simplygon::spSceneExporter sgSceneExporter = sg->CreateSceneExporter();
	std::string outputScenePath = std::string("output\\") + std::string("ReductionWithVisibilityOccluder") + std::string("_") + std::string(path);
	sgSceneExporter->SetExportFilePath(outputScenePath.c_str());
	sgSceneExporter->SetScene(sgScene);
	
	// Run scene exporter. 
	auto exportResult = sgSceneExporter->Run();
	if (Simplygon::Failed(exportResult))
	{
		throw std::exception("Failed to save scene.");
	}
}

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", "CheckLog: 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", "CheckLog: 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", "CheckLog: 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", "CheckLog: No warnings.");
	}
	
	// Error out if Simplygon has errors. 
	if (hasErrors)
	{
		throw std::exception("Processing failed with an error");
	}
}

void RunReduction(Simplygon::ISimplygon* sg)
{
	// Load scene to process. 	
	printf("%s\n", "Load scene to process.");
	Simplygon::spScene sgScene = LoadScene(sg, "../../../Assets/ObscuredTeapot/ObscuredTeapot.obj");
	
	// Create the reduction processor. 
	Simplygon::spReductionProcessor sgReductionProcessor = sg->CreateReductionProcessor();
	sgReductionProcessor->SetScene( sgScene );
	Simplygon::spReductionSettings sgReductionSettings = sgReductionProcessor->GetReductionSettings();
	Simplygon::spVisibilitySettings sgVisibilitySettings = sgReductionProcessor->GetVisibilitySettings();
	
	// Set reduction target to triangle ratio with a ratio of 50%. 
	sgReductionSettings->SetReductionTargets( Simplygon::EStopCondition::All, true, false, false, false );
	sgReductionSettings->SetReductionTargetTriangleRatio( 0.5f );
	
	// Add a selection set to the scene. We'll use this later as a occluder. 
	Simplygon::spSelectionSetTable sgSceneSelectionSetTable = sgScene->GetSelectionSetTable();
	Simplygon::spSelectionSet sgOccluderSelectionSet = sg->CreateSelectionSet();
	sgOccluderSelectionSet->SetName("Occluder");
	Simplygon::spSceneNode sgRootBox002 = sgScene->GetNodeFromPath("Root/Box002");
	if (!sgRootBox002.IsNull())
		sgOccluderSelectionSet->AddItem(sgRootBox002->GetNodeGUID());
	sgSceneSelectionSetTable->AddSelectionSet(sgOccluderSelectionSet);
	
	// Use the occluder previously added. 
	sgVisibilitySettings->SetOccluderSelectionSetName( "Occluder" );
	
	// Enabled GPU based visibility calculations. 
	sgVisibilitySettings->SetComputeVisibilityMode( Simplygon::EComputeVisibilityMode::DirectX );
	
	// Disabled conservative mode. 
	sgVisibilitySettings->SetConservativeMode( false );
	
	// Remove all non visible geometry. 
	sgVisibilitySettings->SetCullOccludedGeometry( true );
	
	// Skip filling nonvisible regions. 
	sgVisibilitySettings->SetFillNonVisibleAreaThreshold( 0.0f );
	
	// Don't remove non occluding triangles. 
	sgVisibilitySettings->SetRemoveTrianglesNotOccludingOtherTriangles( false );
	
	// Remove all back facing triangles. 
	sgVisibilitySettings->SetUseBackfaceCulling( true );
	
	// Don't use visibility weights. 
	sgVisibilitySettings->SetUseVisibilityWeightsInReducer( false );
	
	// Start the reduction process. 	
	printf("%s\n", "Start the reduction process.");
	sgReductionProcessor->RunProcessing();
	
	// Save processed scene. 	
	printf("%s\n", "Save processed scene.");
	SaveScene(sg, sgScene, "Output.fbx");
	
	// 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);
	}

	RunReduction(sg);

	Simplygon::Deinitialize(sg);

	return 0;
}
csharp
// Copyright (c) Microsoft Corporation. 
// Licensed under the MIT License. 

using System;
using System.IO;
using System.Threading.Tasks;

public class Program
{
    static Simplygon.spScene LoadScene(Simplygon.ISimplygon sg, string path)
    {
        // Create scene importer 
        using Simplygon.spSceneImporter sgSceneImporter = sg.CreateSceneImporter();
        sgSceneImporter.SetImportFilePath(path);
        
        // Run scene importer. 
        var importResult = sgSceneImporter.Run();
        if (Simplygon.Simplygon.Failed(importResult))
        {
            throw new System.Exception("Failed to load scene.");
        }
        Simplygon.spScene sgScene = sgSceneImporter.GetScene();
        return sgScene;
    }

    static void SaveScene(Simplygon.ISimplygon sg, Simplygon.spScene sgScene, string path)
    {
        // Create scene exporter. 
        using Simplygon.spSceneExporter sgSceneExporter = sg.CreateSceneExporter();
        string outputScenePath = string.Join("", new string[] { "output\\", "ReductionWithVisibilityOccluder", "_", path });
        sgSceneExporter.SetExportFilePath(outputScenePath);
        sgSceneExporter.SetScene(sgScene);
        
        // Run scene exporter. 
        var exportResult = sgSceneExporter.Run();
        if (Simplygon.Simplygon.Failed(exportResult))
        {
            throw new System.Exception("Failed to save scene.");
        }
    }

    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("CheckLog: Errors:");
                for (uint errorIndex = 0; errorIndex < errorCount; ++errorIndex)
                {
                    string errorString = errors.GetItem((int)errorIndex);
                    Console.WriteLine(errorString);
                }
                sg.ClearErrorMessages();
            }
        }
        else
        {
            Console.WriteLine("CheckLog: 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("CheckLog: Warnings:");
                for (uint warningIndex = 0; warningIndex < warningCount; ++warningIndex)
                {
                    string warningString = warnings.GetItem((int)warningIndex);
                    Console.WriteLine(warningString);
                }
                sg.ClearWarningMessages();
            }
        }
        else
        {
            Console.WriteLine("CheckLog: No warnings.");
        }
        
        // Error out if Simplygon has errors. 
        if (hasErrors)
        {
            throw new System.Exception("Processing failed with an error");
        }
    }

    static void RunReduction(Simplygon.ISimplygon sg)
    {
        // Load scene to process.         
        Console.WriteLine("Load scene to process.");
        Simplygon.spScene sgScene = LoadScene(sg, "../../../Assets/ObscuredTeapot/ObscuredTeapot.obj");
        
        // Create the reduction processor. 
        using Simplygon.spReductionProcessor sgReductionProcessor = sg.CreateReductionProcessor();
        sgReductionProcessor.SetScene( sgScene );
        using Simplygon.spReductionSettings sgReductionSettings = sgReductionProcessor.GetReductionSettings();
        using Simplygon.spVisibilitySettings sgVisibilitySettings = sgReductionProcessor.GetVisibilitySettings();
        
        // Set reduction target to triangle ratio with a ratio of 50%. 
        sgReductionSettings.SetReductionTargets( Simplygon.EStopCondition.All, true, false, false, false );
        sgReductionSettings.SetReductionTargetTriangleRatio( 0.5f );
        
        // Add a selection set to the scene. We'll use this later as a occluder. 
        using Simplygon.spSelectionSetTable sgSceneSelectionSetTable = sgScene.GetSelectionSetTable();
        using Simplygon.spSelectionSet sgOccluderSelectionSet = sg.CreateSelectionSet();
        sgOccluderSelectionSet.SetName("Occluder");
        Simplygon.spSceneNode sgRootBox002 = sgScene.GetNodeFromPath("Root/Box002");
        if (!sgRootBox002.IsNull())
            sgOccluderSelectionSet.AddItem(sgRootBox002.GetNodeGUID());
        sgSceneSelectionSetTable.AddSelectionSet(sgOccluderSelectionSet);
        
        // Use the occluder previously added. 
        sgVisibilitySettings.SetOccluderSelectionSetName( "Occluder" );
        
        // Enabled GPU based visibility calculations. 
        sgVisibilitySettings.SetComputeVisibilityMode( Simplygon.EComputeVisibilityMode.DirectX );
        
        // Disabled conservative mode. 
        sgVisibilitySettings.SetConservativeMode( false );
        
        // Remove all non visible geometry. 
        sgVisibilitySettings.SetCullOccludedGeometry( true );
        
        // Skip filling nonvisible regions. 
        sgVisibilitySettings.SetFillNonVisibleAreaThreshold( 0.0f );
        
        // Don't remove non occluding triangles. 
        sgVisibilitySettings.SetRemoveTrianglesNotOccludingOtherTriangles( false );
        
        // Remove all back facing triangles. 
        sgVisibilitySettings.SetUseBackfaceCulling( true );
        
        // Don't use visibility weights. 
        sgVisibilitySettings.SetUseVisibilityWeightsInReducer( false );
        
        // Start the reduction process.         
        Console.WriteLine("Start the reduction process.");
        sgReductionProcessor.RunProcessing();
        
        // Save processed scene.         
        Console.WriteLine("Save processed scene.");
        SaveScene(sg, sgScene, "Output.fbx");
        
        // 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;
        }
        RunReduction(sg);

        return 0;
    }

}
python
# 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 simplygon10 import simplygon_loader
from simplygon10 import Simplygon


def LoadScene(sg: Simplygon.ISimplygon, path: str):
    # Create scene importer 
    sgSceneImporter = sg.CreateSceneImporter()
    sgSceneImporter.SetImportFilePath(path)
    
    # Run scene importer. 
    importResult = sgSceneImporter.Run()
    if Simplygon.Failed(importResult):
        raise Exception('Failed to load scene.')
    sgScene = sgSceneImporter.GetScene()
    return sgScene

def SaveScene(sg: Simplygon.ISimplygon, sgScene: Simplygon.spScene, path: str):
    # Create scene exporter. 
    sgSceneExporter = sg.CreateSceneExporter()
    outputScenePath = ''.join(['output\\', 'ReductionWithVisibilityOccluder', '_', path])
    sgSceneExporter.SetExportFilePath(outputScenePath)
    sgSceneExporter.SetScene(sgScene)
    
    # Run scene exporter. 
    exportResult = sgSceneExporter.Run()
    if Simplygon.Failed(exportResult):
        raise Exception('Failed to save scene.')

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('CheckLog: Errors:')
            for errorIndex in range(errorCount):
                errorString = errors.GetItem(errorIndex)
                print(errorString)
            sg.ClearErrorMessages()
    else:
        print('CheckLog: 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('CheckLog: Warnings:')
            for warningIndex in range(warningCount):
                warningString = warnings.GetItem(warningIndex)
                print(warningString)
            sg.ClearWarningMessages()
    else:
        print('CheckLog: No warnings.')
    
    # Error out if Simplygon has errors. 
    if hasErrors:
        raise Exception('Processing failed with an error')

def RunReduction(sg: Simplygon.ISimplygon):
    # Load scene to process.     
    print("Load scene to process.")
    sgScene = LoadScene(sg, '../../../Assets/ObscuredTeapot/ObscuredTeapot.obj')
    
    # Create the reduction processor. 
    sgReductionProcessor = sg.CreateReductionProcessor()
    sgReductionProcessor.SetScene( sgScene )
    sgReductionSettings = sgReductionProcessor.GetReductionSettings()
    sgVisibilitySettings = sgReductionProcessor.GetVisibilitySettings()
    
    # Set reduction target to triangle ratio with a ratio of 50%. 
    sgReductionSettings.SetReductionTargets( Simplygon.EStopCondition_All, True, False, False, False )
    sgReductionSettings.SetReductionTargetTriangleRatio( 0.5 )
    
    # Add a selection set to the scene. We'll use this later as a occluder. 
    sgSceneSelectionSetTable = sgScene.GetSelectionSetTable()
    sgOccluderSelectionSet = sg.CreateSelectionSet()
    sgOccluderSelectionSet.SetName("Occluder")
    sgRootBox002 = sgScene.GetNodeFromPath('Root/Box002')
    if sgRootBox002 is not None:
        sgOccluderSelectionSet.AddItem(sgRootBox002.GetNodeGUID())
    sgSceneSelectionSetTable.AddSelectionSet(sgOccluderSelectionSet)
    
    # Use the occluder previously added. 
    sgVisibilitySettings.SetOccluderSelectionSetName( 'Occluder' )
    
    # Enabled GPU based visibility calculations. 
    sgVisibilitySettings.SetComputeVisibilityMode( Simplygon.EComputeVisibilityMode_DirectX )
    
    # Disabled conservative mode. 
    sgVisibilitySettings.SetConservativeMode( False )
    
    # Remove all non visible geometry. 
    sgVisibilitySettings.SetCullOccludedGeometry( True )
    
    # Skip filling nonvisible regions. 
    sgVisibilitySettings.SetFillNonVisibleAreaThreshold( 0.0 )
    
    # Don't remove non occluding triangles. 
    sgVisibilitySettings.SetRemoveTrianglesNotOccludingOtherTriangles( False )
    
    # Remove all back facing triangles. 
    sgVisibilitySettings.SetUseBackfaceCulling( True )
    
    # Don't use visibility weights. 
    sgVisibilitySettings.SetUseVisibilityWeightsInReducer( False )
    
    # Start the reduction process.     
    print("Start the reduction process.")
    sgReductionProcessor.RunProcessing()
    
    # Save processed scene.     
    print("Save processed scene.")
    SaveScene(sg, sgScene, 'Output.fbx')
    
    # 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())

        RunReduction(sg)

        sg = None
        gc.collect()

Camera from geometry vertices example

This example shows how to use the Reduction processor with a visibility cameras generated from an arbitrary geometry.

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

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


Simplygon::spScene LoadScene(Simplygon::ISimplygon* sg, const char* path)
{
	// Create scene importer 
	Simplygon::spSceneImporter sgSceneImporter = sg->CreateSceneImporter();
	sgSceneImporter->SetImportFilePath(path);
	
	// Run scene importer. 
	auto importResult = sgSceneImporter->Run();
	if (Simplygon::Failed(importResult))
	{
		throw std::exception("Failed to load scene.");
	}
	Simplygon::spScene sgScene = sgSceneImporter->GetScene();
	return sgScene;
}

void SaveScene(Simplygon::ISimplygon* sg, Simplygon::spScene sgScene, const char* path)
{
	// Create scene exporter. 
	Simplygon::spSceneExporter sgSceneExporter = sg->CreateSceneExporter();
	std::string outputScenePath = std::string("output\\") + std::string("ReductionWithVisibilityCameraFromGeometry") + std::string("_") + std::string(path);
	sgSceneExporter->SetExportFilePath(outputScenePath.c_str());
	sgSceneExporter->SetScene(sgScene);
	
	// Run scene exporter. 
	auto exportResult = sgSceneExporter->Run();
	if (Simplygon::Failed(exportResult))
	{
		throw std::exception("Failed to save scene.");
	}
}

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", "CheckLog: 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", "CheckLog: 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", "CheckLog: 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", "CheckLog: No warnings.");
	}
	
	// Error out if Simplygon has errors. 
	if (hasErrors)
	{
		throw std::exception("Processing failed with an error");
	}
}

void RunReduction(Simplygon::ISimplygon* sg)
{
	// Load scene to process. 	
	printf("%s\n", "Load scene to process.");
	Simplygon::spScene sgScene = LoadScene(sg, "../../../Assets/ObscuredTeapot/ObscuredTeapot.obj");
	
	// Load camera gemometry 
	Simplygon::spScene sgSceneGeometryCamera = LoadScene(sg, "../../../Assets/ObscuredTeapot/CameraMesh.obj");
	
	// Select Mesh Nodes 
	int selectionSetId = sgSceneGeometryCamera->SelectNodes("ISceneMesh");
	Simplygon::spSelectionSetTable sgSelectionSetsTable = sgSceneGeometryCamera->GetSelectionSetTable();
	Simplygon::spSelectionSet selectionSceneMeshes = sgSelectionSetsTable->GetSelectionSet(selectionSetId);
	auto itemCount = selectionSceneMeshes->GetItemCount();
	Simplygon::spSelectionSet cameraSelectionSet = sg->CreateSelectionSet();
	
	// Copy each mesh from camera scene into a scene and created a camera selection set based on those 
	// ids. 
	for (auto meshIndex = 0U; meshIndex < itemCount; ++meshIndex)
	{
		Simplygon::spString meshNodeId = selectionSceneMeshes->GetItem(meshIndex);
		Simplygon::spSceneNode sceneNode = sgSceneGeometryCamera->GetNodeByGUID(meshNodeId);
		Simplygon::spSceneMesh sceneMesh = Simplygon::spSceneMesh::SafeCast(sceneNode);
		Simplygon::spGeometryData geom = sceneMesh->GetGeometry();
		Simplygon::spSceneMesh cameraMesh = sgScene->GetRootNode()->CreateChildMesh(geom);
		Simplygon::spString nodeId = cameraMesh->GetNodeGUID();
		cameraSelectionSet->AddItem(nodeId);
	}
	int cameraSelectionSetId = sgScene->GetSelectionSetTable()->AddSelectionSet(cameraSelectionSet);
	
	// Create the reduction processor. 
	Simplygon::spReductionProcessor sgReductionProcessor = sg->CreateReductionProcessor();
	
	// Get settings objects 
	Simplygon::spReductionSettings sgReductionSettings = sgReductionProcessor->GetReductionSettings();
	Simplygon::spVisibilitySettings sgVisibilitySettings = sgReductionProcessor->GetVisibilitySettings();
	
	// Set camera selection set id with 
	sgVisibilitySettings->SetCameraSelectionSetID( cameraSelectionSetId );
	
	// Setup visibility setting enable GPU based computation, 
	sgVisibilitySettings->SetUseVisibilityWeightsInReducer( true );
	sgVisibilitySettings->SetUseVisibilityWeightsInTexcoordGenerator( false );
	sgVisibilitySettings->SetComputeVisibilityMode( Simplygon::EComputeVisibilityMode::DirectX );
	sgVisibilitySettings->SetConservativeMode( false );
	sgVisibilitySettings->SetCullOccludedGeometry( true );
	sgVisibilitySettings->SetFillNonVisibleAreaThreshold( 0.0f );
	sgVisibilitySettings->SetRemoveTrianglesNotOccludingOtherTriangles( false );
	sgVisibilitySettings->SetUseBackfaceCulling( true );
	
	// Set reduction target to triangle ratio with a ratio of 50%. 
	sgReductionSettings->SetReductionTargetTriangleRatio( 0.5f );
	sgReductionProcessor->SetScene( sgScene );
	
	// Start the reduction process. 	
	printf("%s\n", "Start the reduction process.");
	sgReductionProcessor->RunProcessing();
	
	// Save processed scene. 	
	printf("%s\n", "Save processed scene.");
	SaveScene(sg, sgScene, "Output.fbx");
	
	// 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);
	}

	RunReduction(sg);

	Simplygon::Deinitialize(sg);

	return 0;
}
csharp
// Copyright (c) Microsoft Corporation. 
// Licensed under the MIT License. 

using System;
using System.IO;
using System.Threading.Tasks;

public class Program
{
    static Simplygon.spScene LoadScene(Simplygon.ISimplygon sg, string path)
    {
        // Create scene importer 
        using Simplygon.spSceneImporter sgSceneImporter = sg.CreateSceneImporter();
        sgSceneImporter.SetImportFilePath(path);
        
        // Run scene importer. 
        var importResult = sgSceneImporter.Run();
        if (Simplygon.Simplygon.Failed(importResult))
        {
            throw new System.Exception("Failed to load scene.");
        }
        Simplygon.spScene sgScene = sgSceneImporter.GetScene();
        return sgScene;
    }

    static void SaveScene(Simplygon.ISimplygon sg, Simplygon.spScene sgScene, string path)
    {
        // Create scene exporter. 
        using Simplygon.spSceneExporter sgSceneExporter = sg.CreateSceneExporter();
        string outputScenePath = string.Join("", new string[] { "output\\", "ReductionWithVisibilityCameraFromGeometry", "_", path });
        sgSceneExporter.SetExportFilePath(outputScenePath);
        sgSceneExporter.SetScene(sgScene);
        
        // Run scene exporter. 
        var exportResult = sgSceneExporter.Run();
        if (Simplygon.Simplygon.Failed(exportResult))
        {
            throw new System.Exception("Failed to save scene.");
        }
    }

    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("CheckLog: Errors:");
                for (uint errorIndex = 0; errorIndex < errorCount; ++errorIndex)
                {
                    string errorString = errors.GetItem((int)errorIndex);
                    Console.WriteLine(errorString);
                }
                sg.ClearErrorMessages();
            }
        }
        else
        {
            Console.WriteLine("CheckLog: 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("CheckLog: Warnings:");
                for (uint warningIndex = 0; warningIndex < warningCount; ++warningIndex)
                {
                    string warningString = warnings.GetItem((int)warningIndex);
                    Console.WriteLine(warningString);
                }
                sg.ClearWarningMessages();
            }
        }
        else
        {
            Console.WriteLine("CheckLog: No warnings.");
        }
        
        // Error out if Simplygon has errors. 
        if (hasErrors)
        {
            throw new System.Exception("Processing failed with an error");
        }
    }

    static void RunReduction(Simplygon.ISimplygon sg)
    {
        // Load scene to process.         
        Console.WriteLine("Load scene to process.");
        Simplygon.spScene sgScene = LoadScene(sg, "../../../Assets/ObscuredTeapot/ObscuredTeapot.obj");
        
        // Load camera gemometry 
        Simplygon.spScene sgSceneGeometryCamera = LoadScene(sg, "../../../Assets/ObscuredTeapot/CameraMesh.obj");
        
        // Select Mesh Nodes 
        int selectionSetId = sgSceneGeometryCamera.SelectNodes("ISceneMesh");
        Simplygon.spSelectionSetTable sgSelectionSetsTable = sgSceneGeometryCamera.GetSelectionSetTable();
        Simplygon.spSelectionSet selectionSceneMeshes = sgSelectionSetsTable.GetSelectionSet(selectionSetId);
        var itemCount = selectionSceneMeshes.GetItemCount();
        Simplygon.spSelectionSet cameraSelectionSet = sg.CreateSelectionSet();
        
        // Copy each mesh from camera scene into a scene and created a camera selection set based on those 
        // ids. 
        for (uint meshIndex = 0; meshIndex < itemCount; ++meshIndex)
        {
            string meshNodeId = selectionSceneMeshes.GetItem(meshIndex);
            Simplygon.spSceneNode sceneNode = sgSceneGeometryCamera.GetNodeByGUID(meshNodeId);
            Simplygon.spSceneMesh sceneMesh = Simplygon.spSceneMesh.SafeCast(sceneNode);
            Simplygon.spGeometryData geom = sceneMesh.GetGeometry();
            Simplygon.spSceneMesh cameraMesh = sgScene.GetRootNode().CreateChildMesh(geom);

            string nodeId = cameraMesh.GetNodeGUID();
            cameraSelectionSet.AddItem(nodeId);
        }
        int cameraSelectionSetId = sgScene.GetSelectionSetTable().AddSelectionSet(cameraSelectionSet);

        
        // Create the reduction processor. 
        using Simplygon.spReductionProcessor sgReductionProcessor = sg.CreateReductionProcessor();
        
        // Get settings objects 
        using Simplygon.spReductionSettings sgReductionSettings = sgReductionProcessor.GetReductionSettings();
        using Simplygon.spVisibilitySettings sgVisibilitySettings = sgReductionProcessor.GetVisibilitySettings();
        
        // Set camera selection set id with 
        sgVisibilitySettings.SetCameraSelectionSetID( cameraSelectionSetId );
        
        // Setup visibility setting enable GPU based computation, 
        sgVisibilitySettings.SetUseVisibilityWeightsInReducer( true );
        sgVisibilitySettings.SetUseVisibilityWeightsInTexcoordGenerator( false );
        sgVisibilitySettings.SetComputeVisibilityMode( Simplygon.EComputeVisibilityMode.DirectX );
        sgVisibilitySettings.SetConservativeMode( false );
        sgVisibilitySettings.SetCullOccludedGeometry( true );
        sgVisibilitySettings.SetFillNonVisibleAreaThreshold( 0.0f );
        sgVisibilitySettings.SetRemoveTrianglesNotOccludingOtherTriangles( false );
        sgVisibilitySettings.SetUseBackfaceCulling( true );
        
        // Set reduction target to triangle ratio with a ratio of 50%. 
        sgReductionSettings.SetReductionTargetTriangleRatio( 0.5f );
        sgReductionProcessor.SetScene( sgScene );
        
        // Start the reduction process.         
        Console.WriteLine("Start the reduction process.");
        sgReductionProcessor.RunProcessing();
        
        // Save processed scene.         
        Console.WriteLine("Save processed scene.");
        SaveScene(sg, sgScene, "Output.fbx");
        
        // 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;
        }
        RunReduction(sg);

        return 0;
    }

}
python
# 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 simplygon10 import simplygon_loader
from simplygon10 import Simplygon


def LoadScene(sg: Simplygon.ISimplygon, path: str):
    # Create scene importer 
    sgSceneImporter = sg.CreateSceneImporter()
    sgSceneImporter.SetImportFilePath(path)
    
    # Run scene importer. 
    importResult = sgSceneImporter.Run()
    if Simplygon.Failed(importResult):
        raise Exception('Failed to load scene.')
    sgScene = sgSceneImporter.GetScene()
    return sgScene

def SaveScene(sg: Simplygon.ISimplygon, sgScene: Simplygon.spScene, path: str):
    # Create scene exporter. 
    sgSceneExporter = sg.CreateSceneExporter()
    outputScenePath = ''.join(['output\\', 'ReductionWithVisibilityCameraFromGeometry', '_', path])
    sgSceneExporter.SetExportFilePath(outputScenePath)
    sgSceneExporter.SetScene(sgScene)
    
    # Run scene exporter. 
    exportResult = sgSceneExporter.Run()
    if Simplygon.Failed(exportResult):
        raise Exception('Failed to save scene.')

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('CheckLog: Errors:')
            for errorIndex in range(errorCount):
                errorString = errors.GetItem(errorIndex)
                print(errorString)
            sg.ClearErrorMessages()
    else:
        print('CheckLog: 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('CheckLog: Warnings:')
            for warningIndex in range(warningCount):
                warningString = warnings.GetItem(warningIndex)
                print(warningString)
            sg.ClearWarningMessages()
    else:
        print('CheckLog: No warnings.')
    
    # Error out if Simplygon has errors. 
    if hasErrors:
        raise Exception('Processing failed with an error')

def RunReduction(sg: Simplygon.ISimplygon):
    # Load scene to process.     
    print("Load scene to process.")
    sgScene = LoadScene(sg, '../../../Assets/ObscuredTeapot/ObscuredTeapot.obj')
    
    # Load camera gemometry 
    sgSceneGeometryCamera = LoadScene(sg, '../../../Assets/ObscuredTeapot/CameraMesh.obj')
    
    # Select Mesh Nodes 
    selectionSetId = sgSceneGeometryCamera.SelectNodes('ISceneMesh')
    sgSelectionSetsTable = sgSceneGeometryCamera.GetSelectionSetTable()
    selectionSceneMeshes = sgSelectionSetsTable.GetSelectionSet(selectionSetId)
    itemCount = selectionSceneMeshes.GetItemCount()
    cameraSelectionSet = sg.CreateSelectionSet()
    
    # Copy each mesh from camera scene into a scene and created a camera selection set based on those 
    # ids. 
    for meshIndex in range(itemCount):
        meshNodeId = selectionSceneMeshes.GetItem(meshIndex)
        sceneNode = sgSceneGeometryCamera.GetNodeByGUID(meshNodeId)
        sceneMesh = Simplygon.spSceneMesh.SafeCast(sceneNode)
        geom = sceneMesh.GetGeometry()
        cameraMesh = sgScene.GetRootNode().CreateChildMesh(geom)

        nodeId = cameraMesh.GetNodeGUID()
        cameraSelectionSet.AddItem(nodeId)
    cameraSelectionSetId = sgScene.GetSelectionSetTable().AddSelectionSet(cameraSelectionSet)

    
    # Create the reduction processor. 
    sgReductionProcessor = sg.CreateReductionProcessor()
    
    # Get settings objects 
    sgReductionSettings = sgReductionProcessor.GetReductionSettings()
    sgVisibilitySettings = sgReductionProcessor.GetVisibilitySettings()
    
    # Set camera selection set id with 
    sgVisibilitySettings.SetCameraSelectionSetID( cameraSelectionSetId )
    
    # Setup visibility setting enable GPU based computation, 
    sgVisibilitySettings.SetUseVisibilityWeightsInReducer( True )
    sgVisibilitySettings.SetUseVisibilityWeightsInTexcoordGenerator( False )
    sgVisibilitySettings.SetComputeVisibilityMode( Simplygon.EComputeVisibilityMode_DirectX )
    sgVisibilitySettings.SetConservativeMode( False )
    sgVisibilitySettings.SetCullOccludedGeometry( True )
    sgVisibilitySettings.SetFillNonVisibleAreaThreshold( 0.0 )
    sgVisibilitySettings.SetRemoveTrianglesNotOccludingOtherTriangles( False )
    sgVisibilitySettings.SetUseBackfaceCulling( True )
    
    # Set reduction target to triangle ratio with a ratio of 50%. 
    sgReductionSettings.SetReductionTargetTriangleRatio( 0.5 )
    sgReductionProcessor.SetScene( sgScene )
    
    # Start the reduction process.     
    print("Start the reduction process.")
    sgReductionProcessor.RunProcessing()
    
    # Save processed scene.     
    print("Save processed scene.")
    SaveScene(sg, sgScene, 'Output.fbx')
    
    # 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())

        RunReduction(sg)

        sg = None
        gc.collect()