# Occlusion mesh processor

The occlusion mesh processor is a relative to the remeshing processor, but it generates the new geometry solely based on the silhouette of the input geometry. This means internal features and concavities will be filled.

The processor is designed in a way that will make the output mesh fall within the bounds of the silhouette of the original mesh at almost all times, making it useful for occlusion culling. Since it removes concavities it is not appropriate for shadow meshes that expect to self-shadow, but for pure casters it works very well. Due to the complexity of the task, this can be quite slow at higher settings.

# Occlusion mesh settings

This settings object contains the relevant settings for occlusion mesh generation, including options like silhouette fidelity and onscreen size.

Occlusion vs original mesh

Occlusion meshes vs original meshes, seen from the front angles.

Occlusion vs original mesh from angle

Occlusion meshes vs original meshes, seen from an angle. Note the filled concavities.

This example shows how to use the Occlusion mesh processor.

//	Copyright (c) Microsoft Corporation.
//	Licensed under the MIT license.
//
//	This example shows how to use the occlusion mesh processor.
//
//  The processor is used to generate three meshes, one occluder (smaller than the original asset),
//	one occludee (larger than the original asset), and one which is the same size as the original.
//  The processor constructs the output meshes based purely on the silhouette of the input, meaning
//	that the resulting meshes are efficient proxies constructed to occlude, and be occluded by,
//	other meshes in occlusion culling rendering and shadow passes. Not suitable for self-shadowing,
//	since they are not depth-conservative, only silhouette-conservative.

#include <string>
#include "SimplygonLoader.h"

void RunOcclusionProcessing(Simplygon::ISimplygon* sg, std::string outputPath, int onScreenSize, int error, Simplygon::EOcclusionMode mode )
{
	Simplygon::spSceneImporter sgSceneImporter = sg->CreateSceneImporter();
	sgSceneImporter->SetImportFilePath( "wall.obj" );
	if( !sgSceneImporter->RunImport() )
		throw std::exception( "Failed to load wall.obj." );
	Simplygon::spScene sgScene = sgSceneImporter->GetScene();

	sgScene->GetMaterialTable()->Clear(); // No materials required for occlusion meshing

	// Create a processor
	Simplygon::spOcclusionMeshProcessor omProcessor = sg->CreateOcclusionMeshProcessor();
	omProcessor->SetScene( sgScene );

	// Set settings
	Simplygon::spOcclusionMeshSettings omSettings = omProcessor->GetOcclusionMeshSettings();
	omSettings->SetOnScreenSize( onScreenSize ); // Determines triangle count / mesh resolution. Generally, we recommend sizes around 100 pixels, currently the
	                                             // algorithm scales badly at larger sizes.
	omSettings->SetOcclusionMode( mode );        // This determines if the output will be smaller or larger than the input.
	omSettings->SetOnScreenErrorTolerance( error ); // This determines the accuracy of the silhouette reconstruction. 1 is the most accurate, larger is faster.
	                                                // Measured in pixels in worst-case setting, so you can easily get away with much larger values.
	// omSettings->SetTransferSkinning( true );
	// omSettings->SetInvertOutputMesh(true); //This inverts the winding, making frontfaces backfaces. Good for more conservative occluders.

	// Run the processing
	omProcessor->RunProcessing();

	Simplygon::spSceneExporter sgSceneExporter = sg->CreateSceneExporter();
	sgSceneExporter->SetScene( sgScene );
	sgSceneExporter->SetExportFilePath( outputPath.c_str() );
	if( !sgSceneExporter->RunExport() )
		throw std::exception( "Failed to save file." );
}

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

	// Create occluder
	RunOcclusionProcessing( sg, "wall_occluder.obj", 100, 10, Simplygon::EOcclusionMode::Occluder );

	// Create occludee
	RunOcclusionProcessing( sg, "wall_occludee.obj", 100, 10, Simplygon::EOcclusionMode::Occludee );

	// Create offscreen shadow mesh, neither larger nor smaller than the original.
	RunOcclusionProcessing( sg, "wall_standard.obj", 100, 10, Simplygon::EOcclusionMode::Standard );

	Simplygon::Deinitialize( sg );
}