OcclusionMeshExample

<< 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!
    }