DataCreationPreferencesExample.cpp

<< Click to Display Table of Contents >>

Navigation:  Simplygon 7.1 examples >

DataCreationPreferencesExample.cpp

///////////////////////////////////////////////////////////////////////////
//
//  System:    Simplygon
//  File:      DataCreationPreferencesExample.cpp
//  Language:  C++
//
//  Copyright (c) 2015 Donya Labs AB. All rights reserved.
//
//  This is private property, and it is illegal to copy or distribute in
//  any form, without written authorization by the copyright owner(s).
//
///////////////////////////////////////////////////////////////////////////
//
//  #Description#
//
//  A wavefront file is opened, the scene is then processed in 3 different ways,
//  one for each data creation preference setting.
//
//  The generated LOD and the original geometry are combined into a single geometry
//  with a shared vertex set.
//
//  All reductions are run with identical settings except for the data creation
//  preferences flag:
//
//  1) SG_DATACREATIONPREFERENCES_ONLY_USE_ORIGINAL_DATA
//  When the reducer is set to only use original data, the new geometry is
//  constructed entirely from vertices present in the original geometry.
//
//  The combined geometry will have the same vertex count as the original.
//
//  2) SG_DATACREATIONPREFERENCES_PREFER_ORIGINAL_DATA
//  When the flag is set to prefer original vertices, mesh repair will be allowed
//  to run on the asset and new combinations of vertex data will be allowed to
//  be created, but most of the vertices will correspond to ones found in the original.
// 
//  The combined geometry will probably have a larger vertex count than the original.
//
//  3) SG_DATACREATIONPREFERENCES_PREFER_OPTIMIZED_RESULT
//  The third setting allows optimization of all vertex data, and produces an
//  entirely new set of vertex coords. The vertices are re-positioned to preserve the
//  original silhouette and volume of the mesh.
//
//  The combined geometry will likely not share vertices between the LOD and original so
//  the combined vertex count is increased.
//
//
//  It should be noted that the most restrictive option original vertices should only
//  be used when the original model is reasonably clean, as all the mesh repair features
//  of Simplygon will be switched off. New normals will not be calculated, vertices
//  will not be welded and T-junctions will not be fixed.
//
//  The results of the three processes are saved as individual .obj files
//
///////////////////////////////////////////////////////////////////////////
#include "../Common/Example.h"
void RunExampleReduction(const std::string& readFrom, const std::string& writeTo, uint DataCreationPref);
int main( int argc , char* argv[] )
    {
    InitExample();
    // Set global variable. Using Orthonormal method for calculating tangentspace.
    sg->SetGlobalSetting( "DefaultTBNType" , SG_TANGENTSPACEMETHOD_ORTHONORMAL );
    std::string assetPath = GetAssetPath();
    // Run the example reduction, use only original vertices
    printf("Running reduction, only using original vertices\n");
    RunExampleReduction( assetPath + "wall.obj", "original_and_lod_original_verts", SG_DATACREATIONPREFERENCES_ONLY_USE_ORIGINAL_DATA );
    printf("Done, output geometry saved to file.\n\n");
    // Run the example reduction, prefer original vertices but still allow new data when required
    printf("Running reduction, allowing creation of new vertices when needed\n");
    RunExampleReduction( assetPath + "wall.obj", "original_and_lod_new_verts", SG_DATACREATIONPREFERENCES_PREFER_ORIGINAL_DATA );
    printf("Done, output geometry saved to file.\n\n");
    // Run the example reduction, optimize all geometry data as required
    printf("Running reduction, allowing modification of all vertex data\n");
    RunExampleReduction( assetPath + "wall.obj", "original_and_lod_optimized_verts", SG_DATACREATIONPREFERENCES_PREFER_OPTIMIZED_RESULT );
    printf("Done, output geometry saved to file.\n");
    DeinitExample();
    return 0;
    }
void RunExampleReduction(const std::string& readFrom, const std::string& writeTo, uint DataCreationPref)
    {
    // Run reduction with default settings to 10% of the original triangle count.
    // The data restrictions flag is set from the main function and determines
    // if the reducer will be allowed to create new vertices or construct the LOD
    // using only the vertices available in the original mesh. The decimated
    // geometry is appended to the packed original, so that the geometry now contains
    // all unique vertices from both the original geometry and the generated LOD.
    // If the data creation flag is set to only use original data no new
    // vertices should be created when the LOD is appended to the original mesh.
    // The LOD triangles described with the combined vertex set is then added to
    // the packed geometry, creating a geometry that contains both the original
    // model and the generated LOD using the same vertices.
    std::string output_geometry_filename = GetExecutablePath() + writeTo + ".obj";
    // Load from file
    spWavefrontImporter objReader = sg->CreateWavefrontImporter();
    objReader->SetImportFilePath( readFrom.c_str() );
    if( !objReader->RunImport() )
        return;
    // Get the scene from the importer
    spScene scene = objReader->GetScene();
    spSelectionSet selectMesh = scene->GetSelectionSetTable()->GetSelectionSet(scene->SelectNodes("ISceneMesh"));
    spGeometryData currentGeom = Cast<ISceneMesh>(scene->GetNodeByGUID(selectMesh->GetItem(0)))->GetGeometry();
    // Create a packed copy of the original geometry for appending to later
    spPackedGeometryData packedGeometry = currentGeom->NewPackedCopy();
    // To compare the combined vertex counts vs the original, we output the original unpacked -> packed geom
    if(true)
        {
        spScene outputOriginalPackedScene = sg->CreateScene();
        outputOriginalPackedScene->GetRootNode()->CreateChildMesh(packedGeometry->NewUnpackedCopy());
        outputOriginalPackedScene->GetMaterialTable()->Copy(scene->GetMaterialTable());
        spWavefrontExporter objexp = sg->CreateWavefrontExporter();
        std::string output_original_unpacked_packed_filename = GetExecutablePath() + "original_unpacked_packed.obj";
        objexp->SetExportFilePath( output_original_unpacked_packed_filename.c_str() );
        objexp->SetScene(outputOriginalPackedScene);
        objexp->RunExport();
        }
    // Create the reduction-processor.
    spReductionProcessor red = sg->CreateReductionProcessor();
    red->SetScene(scene);
    // Set the Reduction Settings.
    spReductionSettings reduction_settings = red->GetReductionSettings();
    // Will reduce to 1/10 of the original trianglecount.
    reduction_settings->SetTriangleRatio( 0.1f );
    // Set the data creation preferences flag
    reduction_settings->SetDataCreationPreferences(DataCreationPref);
    // Run the reduction
    red->RunProcessing();
    // Append processed geometry to original geometry and check number of new vertices
    // Unique vertices from currentGeom will be added to the packed geometry
    // newVertexList will contain a description of the triangles of currentGeom using the
    // original vertex IDs where available.
    // newUniqueVertexCount should increase with the level of freedom allowed for the reducer
    // Note that the geometries need to contain the same set of fields, otherwise the append will fail
    spRidArray newVertexIdsList = sg->CreateRidArray();
    int newUniqueVertexCount = packedGeometry->AppendPackedGeometry(currentGeom, newVertexIdsList, false);
    printf("%i new vertices generated.\n",newUniqueVertexCount);
    // Save original triangle count
    rid originalTriangleCount = packedGeometry->GetTriangleCount();
    // Add the amount of triangles from currentgeom
    packedGeometry->AddTriangles(currentGeom->GetTriangleCount());
    // Append LOD vertex list to the end of the original geometries vertex list
    spRidData newVertexIdsListData = sg->CreateRidData();
    newVertexIdsList->GetData(newVertexIdsListData);
    packedGeometry->GetVertexIds()->SetDataRange( originalTriangleCount*3 , newVertexIdsListData->GetData(), newVertexIdsList->GetItemCount());
    // Append LOD triangle data to the end of the original geometries triangle data
    packedGeometry->GetTriangles()->CopyRange( currentGeom->GetTriangles(), originalTriangleCount, 0, currentGeom->GetTriangleCount());
    // Now, the triangles in packedGeometry describes the original model from 0 <= id < originalTriangleCount,
    // and the generated LOD following that.
    spScene outputCombinedGeometriesScene = sg->CreateScene();
    outputCombinedGeometriesScene->GetRootNode()->CreateChildMesh(packedGeometry->NewUnpackedCopy());
    outputCombinedGeometriesScene->GetMaterialTable()->Copy(scene->GetMaterialTable());
    // Now store combined original and LOD geometry to file
    spWavefrontExporter objexp = sg->CreateWavefrontExporter();
    objexp->SetExportFilePath( output_geometry_filename.c_str() );
    bool outputCombinedScene = true;
    if(outputCombinedScene)
        objexp->SetScene(outputCombinedGeometriesScene); //Output original and LOD sharing vertex list
    else
        objexp->SetScene(scene); //Only output the LOD
    objexp->RunExport();
    }