# Material data
Materials contain color, intensity and multi-layered textures properties for the different channels. There are a number of different standard color channels and the user is also able to create custom user channels.
Materials in Simplygon support multi layered textures. Each channel in a Simplygon material can be composed of multiple texture layers having their own UV set. Multi layered textures for a channel are baked into a single texture while casting based on the blend function, see the casting with texture blend example.
# MaterialTable
The MaterialTable is a collection of materials. The material table is assigned to an object. The material each part of the geometry is using is found in the array of material IDs received when calling GetMaterialIds from the geometry object.
# Material
The Material class contains the material information. Materials are either imported alongside the object or created using the Simplygon API. They are identified by their name or index and the names are set with SetName. Channels for all commonly used PBR and non-PBR material models are pre-defined in Simplygon, and it is possible to add additional user-defined custom channels as well. The channels are defined using shading networks. If a shading network with texture nodes is used, a texture table must also be defined in order to successfully use any of the Simplygon material casters.
AddUserChannel
Creates user channels in the material.ShadingNetwork
Set/get a shading network that will be used instead of the defined texture path or texture image in the relevant channel.
# TextureTable
The TextureTable is a collection of textures. This structure is used by the material casters when casting based on input materials defined by shading networks. Each texture referenced by a texture node in the shading node networks that define the input materials must be represented in this table, which is supplied to the material casters along with the material table.
# Texture
The Texture class contains definition of a single texture. The image data can either be defined using a single file path pointing to the input image, or by setting its ImageData object directly, using the format discussed in the Image Data section. When these are added to the texture table for usage in material casting with node networks, the name, as set by SetName(), is the identifier used to correlate a texture in the shading networks with a texture in the texture table. The Material Casting Example contains an example implementation of how to use this in a casting context properly.
# Material casting
For information about casting materials see the Material Casters section.
# Example
This example shows how to use the Reduction processor with material casting.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include <string>
#include <stdlib.h>
#include <filesystem>
#include <future>
#include "SimplygonLoader.h"
void RunReductionWithMaterialCasting(Simplygon::ISimplygon* sg)
{
Simplygon::spSceneImporter sgSceneImporter = sg->CreateSceneImporter();
sgSceneImporter->SetImportFilePath( "../Assets/SimplygonMan/SimplygonMan.obj" );
if(!sgSceneImporter->RunImport())
throw std::exception("Failed to load SimplygonMan/SimplygonMan.obj.");
Simplygon::spScene sgScene = sgSceneImporter->GetScene();
// Create the reduction processor.
Simplygon::spReductionProcessor sgReductionProcessor = sg->CreateReductionProcessor();
sgReductionProcessor->SetScene( sgScene );
Simplygon::spReductionSettings sgReductionSettings = sgReductionProcessor->GetReductionSettings();
Simplygon::spMappingImageSettings sgMappingImageSettings = sgReductionProcessor->GetMappingImageSettings();
// Set reduction target to triangle ratio with a ratio of 50%.
sgReductionSettings->SetReductionTargets( Simplygon::EStopCondition::All, true, false, false, false );
sgReductionSettings->SetReductionTargetTriangleRatio( 0.5f );
// Generates a mapping image which is used after the reduction to cast new materials to the new
// reduced object.
sgMappingImageSettings->SetGenerateMappingImage( true );
sgMappingImageSettings->SetApplyNewMaterialIds( true );
sgMappingImageSettings->SetGenerateTangents( true );
sgMappingImageSettings->SetUseFullRetexturing( true );
sgMappingImageSettings->SetTexCoordGeneratorType( Simplygon::ETexcoordGeneratorType::ChartAggregator );
Simplygon::spChartAggregatorSettings sgChartAggregatorSettings = sgMappingImageSettings->GetChartAggregatorSettings();
// Enable the chart aggregator and reuse UV space.
sgChartAggregatorSettings->SetChartAggregatorMode( Simplygon::EChartAggregatorMode::SurfaceArea );
sgChartAggregatorSettings->SetSeparateOverlappingCharts( false );
Simplygon::spMappingImageOutputMaterialSettings sgOutputMaterialSettings = sgMappingImageSettings->GetOutputMaterialSettings(0);
// Setting the size of the output material for the mapping image. This will be the output size of the
// textures when we do material casting in a later stage.
sgOutputMaterialSettings->SetTextureWidth( 2048 );
sgOutputMaterialSettings->SetTextureHeight( 2048 );
// Start the reduction process.
sgReductionProcessor->RunProcessing();
// Setup and run the diffuse material casting.
Simplygon::spColorCaster sgDiffuseCaster = sg->CreateColorCaster();
sgDiffuseCaster->SetMappingImage( sgReductionProcessor->GetMappingImage() );
sgDiffuseCaster->SetSourceMaterials( sgScene->GetMaterialTable() );
sgDiffuseCaster->SetSourceTextures( sgScene->GetTextureTable() );
sgDiffuseCaster->SetOutputFilePath( "DiffuseTexture" );
Simplygon::spColorCasterSettings sgDiffuseCasterSettings = sgDiffuseCaster->GetColorCasterSettings();
sgDiffuseCasterSettings->SetMaterialChannel( "Diffuse" );
sgDiffuseCasterSettings->SetOutputImageFileFormat( Simplygon::EImageOutputFormat::PNG );
sgDiffuseCaster->RunProcessing();
std::string diffuseTextureFilePath = sgDiffuseCaster->GetOutputFilePath();
// Setup and run the normals material casting.
Simplygon::spNormalCaster sgNormalsCaster = sg->CreateNormalCaster();
sgNormalsCaster->SetMappingImage( sgReductionProcessor->GetMappingImage() );
sgNormalsCaster->SetSourceMaterials( sgScene->GetMaterialTable() );
sgNormalsCaster->SetSourceTextures( sgScene->GetTextureTable() );
sgNormalsCaster->SetOutputFilePath( "NormalsTexture" );
Simplygon::spNormalCasterSettings sgNormalsCasterSettings = sgNormalsCaster->GetNormalCasterSettings();
sgNormalsCasterSettings->SetMaterialChannel( "Normals" );
sgNormalsCasterSettings->SetGenerateTangentSpaceNormals( true );
sgNormalsCasterSettings->SetOutputImageFileFormat( Simplygon::EImageOutputFormat::PNG );
sgNormalsCaster->RunProcessing();
std::string normalsTextureFilePath = sgNormalsCaster->GetOutputFilePath();
// Update scene with new casted textures.
Simplygon::spMaterialTable sgMaterialTable = sg->CreateMaterialTable();
Simplygon::spTextureTable sgTextureTable = sg->CreateTextureTable();
Simplygon::spMaterial sgMaterial = sg->CreateMaterial();
Simplygon::spTexture sgDiffuseTexture = sg->CreateTexture();
sgDiffuseTexture->SetName( "Diffuse" );
sgDiffuseTexture->SetFilePath( diffuseTextureFilePath.c_str() );
sgTextureTable->AddTexture( sgDiffuseTexture );
Simplygon::spShadingTextureNode sgDiffuseTextureShadingNode = sg->CreateShadingTextureNode();
sgDiffuseTextureShadingNode->SetTexCoordLevel( 0 );
sgDiffuseTextureShadingNode->SetTextureName( "Diffuse" );
sgMaterial->AddMaterialChannel( "Diffuse" );
sgMaterial->SetShadingNetwork( "Diffuse", sgDiffuseTextureShadingNode );
Simplygon::spTexture sgNormalsTexture = sg->CreateTexture();
sgNormalsTexture->SetName( "Normals" );
sgNormalsTexture->SetFilePath( normalsTextureFilePath.c_str() );
sgTextureTable->AddTexture( sgNormalsTexture );
Simplygon::spShadingTextureNode sgNormalsTextureShadingNode = sg->CreateShadingTextureNode();
sgNormalsTextureShadingNode->SetTexCoordLevel( 0 );
sgNormalsTextureShadingNode->SetTextureName( "Normals" );
sgMaterial->AddMaterialChannel( "Normals" );
sgMaterial->SetShadingNetwork( "Normals", sgNormalsTextureShadingNode );
sgMaterialTable->AddMaterial( sgMaterial );
sgScene->GetTextureTable()->Clear();
sgScene->GetMaterialTable()->Clear();
sgScene->GetTextureTable()->Copy(sgTextureTable);
sgScene->GetMaterialTable()->Copy(sgMaterialTable);
Simplygon::spSceneExporter sgSceneExporter = sg->CreateSceneExporter();
sgSceneExporter->SetScene(sgScene);
sgSceneExporter->SetExportFilePath( "ReductionOutput.fbx" );
if(!sgSceneExporter->RunExport())
throw std::exception("Failed to save ReductionOutput.fbx.");
}
void main()
{
Simplygon::ISimplygon* sg = NULL;
Simplygon::EErrorCodes initval = Simplygon::Initialize( &sg );
if( initval != Simplygon::EErrorCodes::NoError )
{
return;
}
RunReductionWithMaterialCasting(sg);
Simplygon::Deinitialize(sg);
}
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
using System;
using System.IO;
using System.Threading.Tasks;
public class Program
{
static void RunReductionWithMaterialCasting(Simplygon.ISimplygon sg)
{
using (Simplygon.spSceneImporter sgSceneImporter = sg.CreateSceneImporter())
{
sgSceneImporter.SetImportFilePath( "../Assets/SimplygonMan/SimplygonMan.obj" );
if(!sgSceneImporter.RunImport())
throw new System.Exception("Failed to load SimplygonMan/SimplygonMan.obj.");
Simplygon.spScene sgScene = sgSceneImporter.GetScene();
// Create the reduction processor.
using (Simplygon.spReductionProcessor sgReductionProcessor = sg.CreateReductionProcessor())
{
sgReductionProcessor.SetScene( sgScene );
using (Simplygon.spReductionSettings sgReductionSettings = sgReductionProcessor.GetReductionSettings())
using (Simplygon.spMappingImageSettings sgMappingImageSettings = sgReductionProcessor.GetMappingImageSettings())
{
// Set reduction target to triangle ratio with a ratio of 50%.
sgReductionSettings.SetReductionTargets( Simplygon.EStopCondition.All, true, false, false, false );
sgReductionSettings.SetReductionTargetTriangleRatio( 0.5f );
// Generates a mapping image which is used after the reduction to cast new materials to the new
// reduced object.
sgMappingImageSettings.SetGenerateMappingImage( true );
sgMappingImageSettings.SetApplyNewMaterialIds( true );
sgMappingImageSettings.SetGenerateTangents( true );
sgMappingImageSettings.SetUseFullRetexturing( true );
sgMappingImageSettings.SetTexCoordGeneratorType( Simplygon.ETexcoordGeneratorType.ChartAggregator );
using (Simplygon.spChartAggregatorSettings sgChartAggregatorSettings = sgMappingImageSettings.GetChartAggregatorSettings())
{
// Enable the chart aggregator and reuse UV space.
sgChartAggregatorSettings.SetChartAggregatorMode( Simplygon.EChartAggregatorMode.SurfaceArea );
sgChartAggregatorSettings.SetSeparateOverlappingCharts( false );
}
using (Simplygon.spMappingImageOutputMaterialSettings sgOutputMaterialSettings = sgMappingImageSettings.GetOutputMaterialSettings(0))
{
// Setting the size of the output material for the mapping image. This will be the output size of the
// textures when we do material casting in a later stage.
sgOutputMaterialSettings.SetTextureWidth( 2048 );
sgOutputMaterialSettings.SetTextureHeight( 2048 );
}
}
// Start the reduction process.
sgReductionProcessor.RunProcessing();
// Setup and run the diffuse material casting.
string diffuseTextureFilePath;
using (Simplygon.spColorCaster sgDiffuseCaster = sg.CreateColorCaster())
{
sgDiffuseCaster.SetMappingImage( sgReductionProcessor.GetMappingImage() );
sgDiffuseCaster.SetSourceMaterials( sgScene.GetMaterialTable() );
sgDiffuseCaster.SetSourceTextures( sgScene.GetTextureTable() );
sgDiffuseCaster.SetOutputFilePath( "DiffuseTexture" );
using (Simplygon.spColorCasterSettings sgDiffuseCasterSettings = sgDiffuseCaster.GetColorCasterSettings())
{
sgDiffuseCasterSettings.SetMaterialChannel( "Diffuse" );
sgDiffuseCasterSettings.SetOutputImageFileFormat( Simplygon.EImageOutputFormat.PNG );
}
sgDiffuseCaster.RunProcessing();
diffuseTextureFilePath = sgDiffuseCaster.GetOutputFilePath();
}
// Setup and run the normals material casting.
string normalsTextureFilePath;
using (Simplygon.spNormalCaster sgNormalsCaster = sg.CreateNormalCaster())
{
sgNormalsCaster.SetMappingImage( sgReductionProcessor.GetMappingImage() );
sgNormalsCaster.SetSourceMaterials( sgScene.GetMaterialTable() );
sgNormalsCaster.SetSourceTextures( sgScene.GetTextureTable() );
sgNormalsCaster.SetOutputFilePath( "NormalsTexture" );
using (Simplygon.spNormalCasterSettings sgNormalsCasterSettings = sgNormalsCaster.GetNormalCasterSettings())
{
sgNormalsCasterSettings.SetMaterialChannel( "Normals" );
sgNormalsCasterSettings.SetGenerateTangentSpaceNormals( true );
sgNormalsCasterSettings.SetOutputImageFileFormat( Simplygon.EImageOutputFormat.PNG );
}
sgNormalsCaster.RunProcessing();
normalsTextureFilePath = sgNormalsCaster.GetOutputFilePath();
}
// Update scene with new casted textures.
using (Simplygon.spMaterialTable sgMaterialTable = sg.CreateMaterialTable())
using (Simplygon.spTextureTable sgTextureTable = sg.CreateTextureTable())
using (Simplygon.spMaterial sgMaterial = sg.CreateMaterial())
{
using(Simplygon.spTexture sgDiffuseTexture = sg.CreateTexture())
{
sgDiffuseTexture.SetName( "Diffuse" );
sgDiffuseTexture.SetFilePath( diffuseTextureFilePath );
sgTextureTable.AddTexture( sgDiffuseTexture );
}
using(Simplygon.spShadingTextureNode sgDiffuseTextureShadingNode = sg.CreateShadingTextureNode())
{
sgDiffuseTextureShadingNode.SetTexCoordLevel( 0 );
sgDiffuseTextureShadingNode.SetTextureName( "Diffuse" );
sgMaterial.AddMaterialChannel( "Diffuse" );
sgMaterial.SetShadingNetwork( "Diffuse", sgDiffuseTextureShadingNode );
}
using(Simplygon.spTexture sgNormalsTexture = sg.CreateTexture())
{
sgNormalsTexture.SetName( "Normals" );
sgNormalsTexture.SetFilePath( normalsTextureFilePath );
sgTextureTable.AddTexture( sgNormalsTexture );
}
using(Simplygon.spShadingTextureNode sgNormalsTextureShadingNode = sg.CreateShadingTextureNode())
{
sgNormalsTextureShadingNode.SetTexCoordLevel( 0 );
sgNormalsTextureShadingNode.SetTextureName( "Normals" );
sgMaterial.AddMaterialChannel( "Normals" );
sgMaterial.SetShadingNetwork( "Normals", sgNormalsTextureShadingNode );
}
sgMaterialTable.AddMaterial( sgMaterial );
sgScene.GetTextureTable().Clear();
sgScene.GetMaterialTable().Clear();
sgScene.GetTextureTable().Copy(sgTextureTable);
sgScene.GetMaterialTable().Copy(sgMaterialTable);
}
}
using (Simplygon.spSceneExporter sgSceneExporter = sg.CreateSceneExporter())
{
sgSceneExporter.SetScene(sgScene);
sgSceneExporter.SetExportFilePath( "ReductionOutput.fbx" );
if(!sgSceneExporter.RunExport())
throw new System.Exception("Failed to save ReductionOutput.fbx.");
}
}
}
static void Main(string[] args)
{
using (var sg = Simplygon.Loader.InitSimplygon(out var errorCode, out var errorMessage))
{
if (errorCode != Simplygon.EErrorCodes.NoError)
return;
RunReductionWithMaterialCasting(sg);
}
}
}
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT license.
import math
import os
import sys
import glob
import gc
import threading
from pathlib import Path
from simplygon import simplygon_loader
from simplygon import Simplygon
def RunReductionWithMaterialCasting(sg: Simplygon.ISimplygon):
sgSceneImporter = sg.CreateSceneImporter()
sgSceneImporter.SetImportFilePath( '../Assets/SimplygonMan/SimplygonMan.obj' )
if not sgSceneImporter.RunImport():
raise Exception('Failed to load SimplygonMan/SimplygonMan.obj.')
sgScene = sgSceneImporter.GetScene()
# Create the reduction processor.
sgReductionProcessor = sg.CreateReductionProcessor()
sgReductionProcessor.SetScene( sgScene )
sgReductionSettings = sgReductionProcessor.GetReductionSettings()
sgMappingImageSettings = sgReductionProcessor.GetMappingImageSettings()
# Set reduction target to triangle ratio with a ratio of 50%.
sgReductionSettings.SetReductionTargets( Simplygon.EStopCondition_All, True, False, False, False )
sgReductionSettings.SetReductionTargetTriangleRatio( 0.5 )
# Generates a mapping image which is used after the reduction to cast new materials to the new
# reduced object.
sgMappingImageSettings.SetGenerateMappingImage( True )
sgMappingImageSettings.SetApplyNewMaterialIds( True )
sgMappingImageSettings.SetGenerateTangents( True )
sgMappingImageSettings.SetUseFullRetexturing( True )
sgMappingImageSettings.SetTexCoordGeneratorType( Simplygon.ETexcoordGeneratorType_ChartAggregator )
sgChartAggregatorSettings = sgMappingImageSettings.GetChartAggregatorSettings()
# Enable the chart aggregator and reuse UV space.
sgChartAggregatorSettings.SetChartAggregatorMode( Simplygon.EChartAggregatorMode_SurfaceArea )
sgChartAggregatorSettings.SetSeparateOverlappingCharts( False )
sgOutputMaterialSettings = sgMappingImageSettings.GetOutputMaterialSettings(0)
# Setting the size of the output material for the mapping image. This will be the output size of the
# textures when we do material casting in a later stage.
sgOutputMaterialSettings.SetTextureWidth( 2048 )
sgOutputMaterialSettings.SetTextureHeight( 2048 )
# Start the reduction process.
sgReductionProcessor.RunProcessing()
# Setup and run the diffuse material casting.
sgDiffuseCaster = sg.CreateColorCaster()
sgDiffuseCaster.SetMappingImage( sgReductionProcessor.GetMappingImage() )
sgDiffuseCaster.SetSourceMaterials( sgScene.GetMaterialTable() )
sgDiffuseCaster.SetSourceTextures( sgScene.GetTextureTable() )
sgDiffuseCaster.SetOutputFilePath( 'DiffuseTexture' )
sgDiffuseCasterSettings = sgDiffuseCaster.GetColorCasterSettings()
sgDiffuseCasterSettings.SetMaterialChannel( 'Diffuse' )
sgDiffuseCasterSettings.SetOutputImageFileFormat( Simplygon.EImageOutputFormat_PNG )
sgDiffuseCaster.RunProcessing()
diffuseTextureFilePath = sgDiffuseCaster.GetOutputFilePath()
# Setup and run the normals material casting.
sgNormalsCaster = sg.CreateNormalCaster()
sgNormalsCaster.SetMappingImage( sgReductionProcessor.GetMappingImage() )
sgNormalsCaster.SetSourceMaterials( sgScene.GetMaterialTable() )
sgNormalsCaster.SetSourceTextures( sgScene.GetTextureTable() )
sgNormalsCaster.SetOutputFilePath( 'NormalsTexture' )
sgNormalsCasterSettings = sgNormalsCaster.GetNormalCasterSettings()
sgNormalsCasterSettings.SetMaterialChannel( 'Normals' )
sgNormalsCasterSettings.SetGenerateTangentSpaceNormals( True )
sgNormalsCasterSettings.SetOutputImageFileFormat( Simplygon.EImageOutputFormat_PNG )
sgNormalsCaster.RunProcessing()
normalsTextureFilePath = sgNormalsCaster.GetOutputFilePath()
# Update scene with new casted textures.
sgMaterialTable = sg.CreateMaterialTable()
sgTextureTable = sg.CreateTextureTable()
sgMaterial = sg.CreateMaterial()
sgDiffuseTexture = sg.CreateTexture()
sgDiffuseTexture.SetName( 'Diffuse' )
sgDiffuseTexture.SetFilePath( diffuseTextureFilePath )
sgTextureTable.AddTexture( sgDiffuseTexture )
sgDiffuseTextureShadingNode = sg.CreateShadingTextureNode()
sgDiffuseTextureShadingNode.SetTexCoordLevel( 0 )
sgDiffuseTextureShadingNode.SetTextureName( 'Diffuse' )
sgMaterial.AddMaterialChannel( 'Diffuse' )
sgMaterial.SetShadingNetwork( 'Diffuse', sgDiffuseTextureShadingNode )
sgNormalsTexture = sg.CreateTexture()
sgNormalsTexture.SetName( 'Normals' )
sgNormalsTexture.SetFilePath( normalsTextureFilePath )
sgTextureTable.AddTexture( sgNormalsTexture )
sgNormalsTextureShadingNode = sg.CreateShadingTextureNode()
sgNormalsTextureShadingNode.SetTexCoordLevel( 0 )
sgNormalsTextureShadingNode.SetTextureName( 'Normals' )
sgMaterial.AddMaterialChannel( 'Normals' )
sgMaterial.SetShadingNetwork( 'Normals', sgNormalsTextureShadingNode )
sgMaterialTable.AddMaterial( sgMaterial )
sgScene.GetTextureTable().Clear()
sgScene.GetMaterialTable().Clear()
sgScene.GetTextureTable().Copy(sgTextureTable)
sgScene.GetMaterialTable().Copy(sgMaterialTable)
sgSceneExporter = sg.CreateSceneExporter()
sgSceneExporter.SetScene(sgScene)
sgSceneExporter.SetExportFilePath( 'ReductionOutput.fbx' )
if not sgSceneExporter.RunExport():
raise Exception('Failed to save ReductionOutput.fbx.')
if __name__ == '__main__':
sg = simplygon_loader.init_simplygon()
if sg is not None:
RunReductionWithMaterialCasting(sg)
sg = None
gc.collect()