TextureVertexWeightsExample.cpp

<< Click to Display Table of Contents >>

Navigation:  Simplygon 7.1 examples >

TextureVertexWeightsExample.cpp

///////////////////////////////////////////////////////////////////////////
//
//  System:    Simplygon
//  File:      TextureVertexWeightsExample.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 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[] )
    {   
    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();
    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() )
        return;
    spScene originalScene = objReader->GetScene();
    spMaterialTable originalMaterials = originalScene->GetMaterialTable();
    spScene lodScene = sg->CreateScene();
    spGeometryData lodGeometry = originalScene->GetCombinedGeometry();
    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();
    // Cast diffuse texture and normal map data into a new material
    // Create new material table.
    spMaterialTable lodMaterials = sg->CreateMaterialTable();
    //  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->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->CastMaterials(); // Fetch!
        // set the material properties
        // Set the diffuse multiplier for the texture. 1 means it will not differ from original texture,
        // For example: 0 would ignore a specified color and 2 would make a color twice as pronounced as the others.
        output_material->SetDiffuseRed(1);
        output_material->SetDiffuseGreen(1);
        output_material->SetDiffuseBlue(1);
        // Set material to point to created texture filename.
        output_material->SetTexture( SG_MATERIAL_CHANNEL_DIFFUSE , output_diffuse_filename.c_str() );
        }
       
    //Add the generated materials to the scene
    lodScene->GetMaterialTable()->Copy(lodMaterials);
    // Store to file
    spWavefrontExporter objexp = sg->CreateWavefrontExporter();
    objexp->SetExportFilePath( output_geometry_filename.c_str() );
    objexp->SetScene( lodScene );
    objexp->RunExport();
    }