Show / Hide Table of Contents
    ///////////////////////////////////////////////////////////////////////////
    //
    //  System:    Simplygon
    //  File:      TextureVertexWeightsExample.cpp
    //  Language:  C++
    //
    //  Copyright (c) 2019 Microsoft. 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 geometry with diffuse textures are loaded. The geometry is assigned 
    //  vertex weights which will determine how important the areas are.
    //
    //  The geometry is reduced to 90% triangles remaining and a materialLOD is 
    //  generated assisted by the vertex weights.
    //
    //  The areas with larger vertex weights will get a larger proportional 
    //  size of the UV texture space area.
    //
    //
    ///////////////////////////////////////////////////////////////////////////
    
    #include "../Common/Example.h"
    
    void RunExample( const std::string& readFrom, const std::string& writeTo );
    
    int main( int argc, char* argv[] )
        {
        try
        {
            InitExample();
    
            // Set global variable. Using Orthonormal method for calculating
            // tangentspace.
            sg->SetGlobalSetting("DefaultTBNType", SG_TANGENTSPACEMETHOD_ORTHONORMAL);
    
            std::string assetPath = GetAssetPath();
    
            // Run the example code
            RunExample(assetPath + "SimplygonMan/SimplygonMan.obj", "SimplygonMan_LOD");
    
            DeinitExample();
        }
        catch (const std::exception& ex)
        {
            std::cerr << ex.what() << std::endl;
            return -1;
        }
    
        return 0;
        }
    
    //Sets the vertices in the "top" part of the model to larger values than the bottom part
    void SetVertexWeights( spGeometryData geom )
        {
        //Get the axis aligned bounding box values
        real inf[3];
        real sup[3];
        geom->GetInf( inf );
        geom->GetSup( sup );
    
        // compute the threshold y-axis value
        // all vertices located above this will have larger weights
        float threshold_y = 0.2f * inf[1] + 0.8f * sup[1];
    
        if( geom->GetVertexWeighting() == NULL )
            {
            geom->AddVertexWeighting();
            }
    
        spRealArray vertex_weights = geom->GetVertexWeighting();
        spRealArray vertex_coords = geom->GetCoords();
    
        for( unsigned int v = 0; v < vertex_weights->GetItemCount(); ++v )
            {
    
            real y = vertex_coords->GetItem( v * 3 + 1 );
            if( y > threshold_y )
                {
                vertex_weights->SetItem( v, 5.0f );
                }
            else
                {
                vertex_weights->SetItem( v, 1.0f );
                }
    
            }
        }
    
    void RunExample( const std::string& readFrom, const std::string& newName )
        {
        // Run reduction with some basic settings.
    
        // Generate the output filenames
        std::string output_geometry_filename = GetExecutablePath() + newName + ".obj";
        std::string output_diffuse_filename = GetExecutablePath() + newName + "_diffuse.png";
    
        // Load from file
        spWavefrontImporter objReader = sg->CreateWavefrontImporter();
        objReader->SetImportFilePath( readFrom.c_str() );
        if( !objReader->RunImport() )
            throw std::exception("Failed to load input file!");
    
        spScene originalScene = objReader->GetScene();
        spMaterialTable originalMaterials = originalScene->GetMaterialTable();
        spTextureTable originalTextures = originalScene->GetTextureTable();
    
        spScene lodScene = sg->CreateScene();
        spGeometryData lodGeometry = originalScene->NewCombinedGeometry();
        lodScene->GetRootNode()->CreateChildMesh( lodGeometry );
        SetVertexWeights( lodGeometry );
    
    
        // Create the reduction-processor.
        spReductionProcessor red = sg->CreateReductionProcessor();
        red->SetScene( lodScene );
    
        // Get the Reduction Settings.
        spReductionSettings reduction_settings = red->GetReductionSettings();
    
        // Will reduce to 9/10 of the original trianglecount.
        reduction_settings->SetTriangleRatio( 0.90f );
    
        //Mapping image settings
        spMappingImageSettings mapping_image_settings = red->GetMappingImageSettings();
        mapping_image_settings->SetGenerateMappingImage( true );
        mapping_image_settings->SetUseFullRetexturing( true );
    
        // Set to generate new texture coordinates.
        mapping_image_settings->SetGenerateTexCoords( true );
    
        // The higher the number, the fewer texture-borders.
        mapping_image_settings->SetParameterizerMaxStretch( 0.6f );
        // Buffer space for when texture is mip-mapped, so color values dont blend over.
        mapping_image_settings->SetGutterSpace( 1 );
    
        mapping_image_settings->SetUseAutomaticTextureSize( false );
        mapping_image_settings->SetWidth( 512 );
        mapping_image_settings->SetHeight( 512 );
        mapping_image_settings->SetMultisamplingLevel( 2 );
    
        //Set the mapping image to use vertex weights
        //This means that areas with larger vertex weights receive larger texture space 
        mapping_image_settings->SetUseVertexWeights( true );
    
        red->RunProcessing();
    
        // Mapping image is needed later on for texture casting.
        spMappingImage mapping_image = red->GetMappingImage();
    
        spTextureTable lodTexTable = lodScene->GetTextureTable();
        lodTexTable->Clear();
        spMaterialTable lodMaterials = lodScene->GetMaterialTable();
        lodMaterials->Clear();
    
        //  Create new material for the table.
        spMaterial output_material = sg->CreateMaterial();
        output_material->SetName( "example_material" );
        lodMaterials->AddMaterial( output_material );
    
        // Cast diffuse texture data
        {
        // Cast the data using a color caster
        spColorCaster cast = sg->CreateColorCaster();
        cast->SetColorType( SG_MATERIAL_CHANNEL_DIFFUSE );
        cast->SetSourceMaterials( originalMaterials );
        cast->SetSourceTextures( originalTextures );
        cast->SetMappingImage( mapping_image ); // The mapping image we got from the remeshing process.
        cast->SetOutputChannels( 3 ); // RGB, 3 channels! (1 would be for gray scale, and 4 would be for RGBA.)
        cast->SetOutputChannelBitDepth( 8 ); // 8 bits per channel. So in this case we will have 24bit colors RGB.
        cast->SetDilation( 10 ); // To avoid mip-map artifacts, the empty pixels on the map needs to be filled to a degree as well.
        cast->SetOutputFilePath( output_diffuse_filename.c_str() ); // Where the texture map will be saved to file.
        cast->RunProcessing(); // Fetch!
    
        // Set material to point to created texture filename.
        spTexture newTex = sg->CreateTexture();
        newTex->SetFilePath( output_diffuse_filename.c_str() );
        newTex->SetName( "Diffuse" );
        lodTexTable->AddTexture( newTex );
        spShadingTextureNode texNode = sg->CreateShadingTextureNode();
        texNode->SetTextureName( "Diffuse" );
        output_material->SetShadingNetwork( SG_MATERIAL_CHANNEL_DIFFUSE, texNode );
        }
    
        // Store to file
        spWavefrontExporter objexp = sg->CreateWavefrontExporter();
    
        objexp->SetExportFilePath( output_geometry_filename.c_str() );
        objexp->SetScene( lodScene );
        objexp->RunExport();
        }
    
    Back to top Terms of Use | Privacy and cookies | Trademarks | Copyright © 2019 Microsoft