CastingWithTextureBlendExample.cpp

<< Click to Display Table of Contents >>

Navigation:  Simplygon 7.1 examples >

CastingWithTextureBlendExample.cpp

///////////////////////////////////////////////////////////////////////////
//
//  System:    Simplygon
//  File:      CastingWithBlendingExample.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#
//
//  Run a reduction process on a geometry that has a multi layered material.
//  The multi layered material has multiple textures and a blend type for
//  how each should blend (add/multiply/subtract etc.).
//  Then perform a material cast onto the LOD, where the multi layered
//  material is baked into a single texture.
//
///////////////////////////////////////////////////////////////////////////
#include "../Common/Example.h"
void MultiLayeredTextureMapping(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
    MultiLayeredTextureMapping( assetPath + "multi.obj", "multi_out" );
    DeinitExample();
    return 0;
    }
void MultiLayeredTextureMapping(const std::string& readFrom, const std::string& writeTo)
    {
    // Run a reduction process on a geometry that has a multi layered material.
    // Then perform a material cast onto the LOD, where the multi layered
    // material is baked into a single texture.
    std::string assetPath = GetAssetPath();
    std::string exePath = GetExecutablePath();
    std::string output_geometry_filename = exePath + writeTo + ".obj";
    std::string output_diffuse_filename = exePath + writeTo + "_diffuse.png";
    std::string output_normals_filename = exePath + writeTo + "_normals.png";
    // Load from file
    spWavefrontImporter objReader = sg->CreateWavefrontImporter();
    objReader->SetImportFilePath( readFrom.c_str() );
    if( !objReader->RunImport() )
        return;
    spScene scene = objReader->GetScene();
    spMaterialTable sceneMaterials = scene->GetMaterialTable();
    spMaterial diffuseMaterial = sg->CreateMaterial();
    //set the number of layers the diffuse channel will use
    diffuseMaterial->SetLayeredTextureSize(SG_MATERIAL_CHANNEL_DIFFUSE,4);
    if(true)
        {
        std::string diffuseBaseFile = assetPath + "base.jpg";
        //import diffuse layer 0 texture (base)
        spImageDataImporter diffuseBase = sg->CreateImageDataImporter();
        diffuseBase->SetImportFilePath( diffuseBaseFile.c_str() );
        diffuseBase->RunImport();
        //set the diffuse material layer 0 (base texture)
        diffuseMaterial->SetLayeredTexture(SG_MATERIAL_CHANNEL_DIFFUSE,0,diffuseBaseFile.c_str());
        diffuseMaterial->SetLayeredTextureLevel(SG_MATERIAL_CHANNEL_DIFFUSE,0,0);
        // set the default blend operation on the diffuse texture (color replace)
        diffuseMaterial->SetLayeredTextureBlendType(SG_MATERIAL_CHANNEL_DIFFUSE,0,SG_TEXTUREBLEND_REPLACE);
        diffuseMaterial->SetLayeredTextureImage(SG_MATERIAL_CHANNEL_DIFFUSE,0,diffuseBase->GetImage());
        }
    if(true)
        {
        std::string diffuseAddFile = assetPath + "add.jpg";
        //import diffuse layer 1 texture (add)
        spImageDataImporter diffuseAdd = sg->CreateImageDataImporter();
        diffuseAdd->SetImportFilePath( diffuseAddFile.c_str() );
        diffuseAdd->RunImport();
        //set the diffuse material layer 1 (add texture)
        diffuseMaterial->SetLayeredTexture(SG_MATERIAL_CHANNEL_DIFFUSE,1,diffuseAddFile.c_str());
        diffuseMaterial->SetLayeredTextureLevel(SG_MATERIAL_CHANNEL_DIFFUSE,1,0);
        // set an additive blend operation of layer 1 texture. This layer would be merge into the base
        diffuseMaterial->SetLayeredTextureBlendType(SG_MATERIAL_CHANNEL_DIFFUSE,1,SG_TEXTUREBLEND_ADD);
        diffuseMaterial->SetLayeredTextureImage(SG_MATERIAL_CHANNEL_DIFFUSE,1,diffuseAdd->GetImage());
        }
    if(true)
        {
        std::string diffuseSubtractFile = assetPath + "subtract.jpg";
        //load layer 2 texture
        spImageDataImporter diffuseSub = sg->CreateImageDataImporter();
        diffuseSub->SetImportFilePath( diffuseSubtractFile.c_str() );
        diffuseSub->RunImport();
        //set the diffuse material layer 2 (subtract texture)
        diffuseMaterial->SetLayeredTexture(SG_MATERIAL_CHANNEL_DIFFUSE,2,diffuseSubtractFile.c_str());
        diffuseMaterial->SetLayeredTextureLevel(SG_MATERIAL_CHANNEL_DIFFUSE,2,0);
        // set an subtractive blend operation on layer 2 texture.
        diffuseMaterial->SetLayeredTextureBlendType(SG_MATERIAL_CHANNEL_DIFFUSE,2,SG_TEXTUREBLEND_SUBTRACT);
        diffuseMaterial->SetLayeredTextureImage(SG_MATERIAL_CHANNEL_DIFFUSE,2,diffuseSub->GetImage());
        }
    if(true)
        {
        std::string diffuseMultiplyFile = assetPath + "multiply.jpg";
        //load layer 3 texture
        spImageDataImporter diffuseMul = sg->CreateImageDataImporter();
        diffuseMul->SetImportFilePath( diffuseMultiplyFile.c_str() );
        diffuseMul->RunImport();
        //set the diffuse material layer 3 (multiply texture)
        diffuseMaterial->SetLayeredTexture(SG_MATERIAL_CHANNEL_DIFFUSE,3,diffuseMultiplyFile.c_str());
        diffuseMaterial->SetLayeredTextureLevel(SG_MATERIAL_CHANNEL_DIFFUSE,3,0);
        diffuseMaterial->SetLayeredTextureBlendType(SG_MATERIAL_CHANNEL_DIFFUSE,3,SG_TEXTUREBLEND_MULTIPLY);
        diffuseMaterial->SetLayeredTextureImage(SG_MATERIAL_CHANNEL_DIFFUSE,3,diffuseMul->GetImage());
        }
    sceneMaterials->Clear();
    sceneMaterials->AddMaterial(diffuseMaterial);
    spReductionProcessor red = sg->CreateReductionProcessor();
    red->SetScene( scene );
    // Find length of the diagonal of the geometry.
    scene->CalculateExtents();
    float inf[3], sup[3];
    scene->GetInf(inf);
    scene->GetSup(sup);
    float geom_diameter = 0.0f;
    geom_diameter += (inf[0] - sup[0])*(inf[0] - sup[0]);
    geom_diameter += (inf[1] - sup[1])*(inf[1] - sup[1]);
    geom_diameter += (inf[2] - sup[2])*(inf[2] - sup[2]);
    geom_diameter = sqrt(geom_diameter);
    // Set the Repair Settings.
    spRepairSettings repair_settings = red->GetRepairSettings();
    // Will take care of holes that are of size 0.2 or less, so small gaps etc are removed.
    repair_settings->SetWeldDist( 0.2f );
    repair_settings->SetTjuncDist( 0.2f );
    // Set the Reduction Settings.
    spReductionSettings reduction_settings = red->GetReductionSettings();
    // The geometry will be reduced to be optimally displayed when the diagonal on-screen-size is around 40 pixels
    // or less. More in detail: the max error of the geometry will be one hundredth of the geometry's size.
    reduction_settings->SetMaxDeviation( geom_diameter / 40.f );
    // Set the Normal Calculation Settings.
    spNormalCalculationSettings normal_settings = red->GetNormalCalculationSettings();
    normal_settings->SetReplaceNormals( true );
    normal_settings->SetHardEdgeAngleInRadians( 3.14159f * 90.f / 180.0f );
    // Set the Image Mapping Settings.
    spMappingImageSettings mapping_settings = red->GetMappingImageSettings();
    // Without this we cannot fetch data from the original geometry, and thus not
    // generate diffuse and normalmaps later on.
    mapping_settings->SetGenerateMappingImage( true );
    // Set to generate new texture coordinates.
    mapping_settings->SetUseFullRetexturing( true ) ;
    mapping_settings->SetGenerateTexCoords( true );
    // The higher the number, the fewer texture-borders.
    mapping_settings->SetParameterizerMaxStretch( 0.6f );
    // Buffer space for when texture is mip-mapped, so color values dont blend over.
    mapping_settings->SetGutterSpace( 4 );
    mapping_settings->SetWidth( 512 );
    mapping_settings->SetHeight( 512 );
    mapping_settings->SetMultisamplingLevel( 2 );
    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 output_materials = sg->CreateMaterialTable();
    //  Create new material for the table.
    spMaterial output_material = sg->CreateMaterial();
    output_material->SetName( "example_material" );
    output_materials->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( sceneMaterials );
        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() );
        }
    //Copy the new material table to the reduced scene
    scene->GetMaterialTable()->Copy(output_materials);
    spWavefrontExporter objexp = sg->CreateWavefrontExporter();
    objexp->SetExportFilePath( output_geometry_filename.c_str() );
    objexp->SetScene( scene );
    objexp->RunExport();
    }