<< Click to Display Table of Contents >> Navigation: Simplygon 7.1 examples > OcclusionMeshExample |
///////////////////////////////////////////////////////////////////////////
//
// System: Simplygon
// File: OcclusionMeshExample.cpp
// Language: C++
//
// Copyright (c) 2015 Donya Labs AB. All rights reserved.
//
///////////////////////////////////////////////////////////////////////////
//
// #Description# An occlusion mesh example
//
// This example shows how to use the occlusion mesh processor.
//
// The processor is used to generate two meshes, one occluder (smaller than the original asset)
// and one occludee (larger than the original asset).
// 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 "../Common/Example.h"
void RunOcclusionProcessing(const std::string& readFrom, const std::string& writeTo, int onScreenSize, int error, int mode);
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
PrintProgressBar(val);
}
}
} progressObserver;
/////////////////////////////////////////////////////////////////////
// Main function with startup and shutdown code
int main( int argc , char* argv[] )
{
InitExample();
std::string assetPath = GetAssetPath();
// Create occluder
printf("Running wall asset, generating occluder...\n");
PrintProgressBar(0); //Initial progress bar
RunOcclusionProcessing( assetPath + "wall.obj", "wall_occluder", 100, 10, SG_OCCLUSIONMODE_OCCLUDER );
printf("\nDone.\n\n");
// Create occludee
printf("Running wall asset, generating occludee...\n");
PrintProgressBar(0); //Initial progress bar
RunOcclusionProcessing( assetPath + "wall.obj", "wall_occludee", 100, 10, SG_OCCLUSIONMODE_OCCLUDEE );
printf("\nDone.\n\n");
// Done!
printf("All LODs complete, shutting down...");
DeinitExample();
return 0;
}
//////////////////////////////////////////////////////////////////////
void RunOcclusionProcessing(const std::string& readFrom, const std::string& writeTo, int onScreenSize, int error, int mode)
{
//Setup output paths
std::string outputGeomPath = GetExecutablePath() + writeTo + ".obj";
//Load input geometry from file
spWavefrontImporter objReader = sg->CreateWavefrontImporter();
objReader->SetExtractGroups(false); //This makes the .obj reader import into a single geometry object instead of multiple
objReader->SetImportFilePath( readFrom.c_str() );
if( !objReader->RunImport() )
return;
//Get the scene from the importer
spScene scene = objReader->GetScene();
scene->GetMaterialTable()->Clear(); //No materials required for occlusion meshing
//Create a processor
spOcclusionMeshProcessor omProcessor = sg->CreateOcclusionMeshProcessor();
omProcessor->SetScene(scene);
//Set settings
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->SetInvertOutputMesh(true); //This inverts the winding, making frontfaces backfaces. Good for guaranteed conservative occluders.
omProcessor->AddObserver( &progressObserver , SG_EVENT_PROGRESS ); //Add progress observer
//Run the processing
omProcessor->RunProcessing();
//Create an .obj exporter to save our result
spWavefrontExporter objExporter = sg->CreateWavefrontExporter();
// Do the actual exporting
objExporter->SetExportFilePath( outputGeomPath.c_str() );
objExporter->SetScene( scene ); //scene now contains the remeshed geometry and the material table we modified above
objExporter->RunExport();
//Done!
}