///////////////////////////////////////////////////////////////////////////
//
// System: Simplygon
// File: VertexColorBakingExample.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#
//
// Utilizes the VertexColorBaker to bake all a specific channel of the
// materials into a vertex color field.
//
//
///////////////////////////////////////////////////////////////////////////
#include "../Common/Example.h"
void RunBakingTesting( const std::string& readFrom, const std::string& writeToBaked );
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
//
RunBakingTesting(assetPath + "SimplygonMan/SimplygonMan.obj", "SimplygonMan_bakedDiffuse");
DeinitExample();
}
catch (const std::exception& ex)
{
std::cerr << ex.what() << std::endl;
return -1;
}
return 0;
}
void RunBakingTesting( const std::string& readFrom, const std::string& writeToBaked )
{
// Import geometries from a file and optimize them. Generate a mapping image
// from the LOD to the original that will be used to sample the materials and
// populate the vertex color field.
// Generate the output filenames
//
std::string output_geometry_baked_filename = writeToBaked + ".sgscene";
// Load object from file
//
spWavefrontImporter objReader = sg->CreateWavefrontImporter();
objReader->SetImportFilePath( readFrom.c_str() );
if( !objReader->RunImport() )
throw std::exception("Failed to load input file!");
spScene scene = objReader->GetScene();
// Reducer
//
spReductionProcessor reducer = sg->CreateReductionProcessor();
reducer->SetScene( scene );
// Set the Repair Settings.
//
spRepairSettings repairSettings = reducer->GetRepairSettings();
repairSettings->SetWeldDist( 0.0f );
repairSettings->SetTjuncDist( 0.0f );
// Set the Reduction Settings.
//
spReductionSettings reductionSettings = reducer->GetReductionSettings();
reductionSettings->SetTriangleRatio( 0.5 );
// Set the Image Mapping Settings.
//
spMappingImageSettings mappingSettings = reducer->GetMappingImageSettings();
// Without this we cannot fetch data from the original geometry, and thus not
// populate the vertex color field
//
mappingSettings->SetGenerateMappingImage( true );
// The higher the number, the fewer texture-borders.
//
mappingSettings->SetParameterizerMaxStretch( 0.5f );
mappingSettings->SetGutterSpace( 1 );
// When only using the mapping image to bake to vert colors, the resolution and super-sampling
// effectively decides how many samples will be used for each vertex. Higher sizes means better quality.
//
mappingSettings->SetWidth( 1024 );
mappingSettings->SetHeight( 1024 );
mappingSettings->SetMultisamplingLevel( 1 );
// If the asset does not already have unique UVs per vertex, i.e. many textures or mirrored UVs,
// a new unique UV set will need to be generated for the mapping image.
//
mappingSettings->SetGenerateTexCoords( true );
mappingSettings->SetTexCoordLevel( (SG_NUM_SUPPORTED_TEXTURE_CHANNELS - 1) );
reducer->RunProcessing();
// Mapping image has now been generated
//
spMappingImage mappingImage = reducer->GetMappingImage();
// Now, finally, bake the entire diffuse channel into color field 0
//
spVertexColorBaker baker = sg->CreateVertexColorBaker();
baker->SetScene( scene ); // The geometry in which you want to create the new vertex color field
baker->SetMappingImage( mappingImage ); // The mapping image mapping the original geometry to the geometry set above
baker->SetSourceMaterials( scene->GetMaterialTable() ); // The material table from which the sampling will be done
baker->SetSourceTextures( scene->GetTextureTable() );
baker->SetChannelName( SG_MATERIAL_CHANNEL_DIFFUSE ); // The channel that will be cast to the color field
baker->SetOutputColorLevelName( "0" ); // The output color level
baker->SetColorSpaceEdgeThreshold( 3.0 ); // This will determine how many "hard borders" will exist in the color field
// It is essentially a RGBA color space difference threshold, where smaller distances are merged.
// This means that the largest distance is sqrt(4) = 2, so 3.0 will produce all smooth borders.
baker->Bake();
// Since .obj does not support colors, we export the result as a scene binary.
//
scene->SaveToFile( output_geometry_baked_filename.c_str() );
///////////////////////////////////
//Output a map of the vertex colors
spScene sceneWithVertexColors = sg->CreateScene();
sceneWithVertexColors->LoadFromFile(output_geometry_baked_filename.c_str());
spGeometryData geom = sceneWithVertexColors->NewCombinedGeometry();
spRealArray colors = geom->GetColors(0);
sceneWithVertexColors->GetTextureTable()->Clear();
sceneWithVertexColors->GetMaterialTable()->Clear();
spShadingVertexColorNode exitNode = sg->CreateShadingVertexColorNode();
exitNode->SetVertexColorIndex(0);
spMaterial mat = sg->CreateMaterial();
mat->SetShadingNetwork(SG_MATERIAL_CHANNEL_DIFFUSE, exitNode);
sceneWithVertexColors->GetMaterialTable()->AddMaterial(mat);
//Use the reduction processor to generate the mapping image needed for outputting the vertex color map
spReductionProcessor red = sg->CreateReductionProcessor();
red->SetScene(sceneWithVertexColors);
red->GetMappingImageSettings()->SetGenerateMappingImage(true);
red->GetMappingImageSettings()->SetUseFullRetexturing(true);
red->RunProcessing();
int id = sceneWithVertexColors->SelectNodes("ISceneMesh");
spSelectionSet set = sceneWithVertexColors->GetSelectionSetTable()->GetSelectionSet(id);
for (uint i = 0; i < set->GetItemCount(); ++i)
{
spGeometryData geomWithVertexColors = SafeCast<ISceneMesh>(sceneWithVertexColors->GetNodeByGUID(set->GetItem(i)))->GetGeometry();
for (uint m = 0; m < geomWithVertexColors->GetMaterialIds()->GetItemCount(); ++m)
{
geomWithVertexColors->GetMaterialIds()->SetItem(m, 0);
}
}
//Use a colorcaster to output the vertex colors
spColorCaster caster = sg->CreateColorCaster();
caster->SetSourceMaterials(sceneWithVertexColors->GetMaterialTable());
caster->SetMappingImage(red->GetMappingImage());
caster->SetColorType(SG_MATERIAL_CHANNEL_DIFFUSE);
caster->SetOutputFilePath("vertexcolors.png");
caster->RunProcessing();
}