This example shows how to use Geomorph. The processed scene will contain reduced geometry mesh nodes, each of which in turn holds an additional child mesh node containing a geomorph geometry that shows how original vertices have moved during reduction. Blend geometries between original and geomorph geometries are then generated in steps of 1/10 and stored to file, to show how the morph-data can be used.
cpp
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#include <string>
#include <stdlib.h>
#include <filesystem>
#include <future>
#include <vector>
#include "SimplygonLoader.h"
Simplygon::spScene LoadScene(Simplygon::ISimplygon* sg, const char* path)
{
// Create scene importer
Simplygon::spSceneImporter sgSceneImporter = sg->CreateSceneImporter();
sgSceneImporter->SetImportFilePath(path);
// Run scene importer.
auto importResult = sgSceneImporter->Run();
if (Simplygon::Failed(importResult))
{
throw std::exception("Failed to load scene.");
}
Simplygon::spScene sgScene = sgSceneImporter->GetScene();
return sgScene;
}
void SaveScene(Simplygon::ISimplygon* sg, Simplygon::spScene sgScene, const char* path)
{
// Create scene exporter.
Simplygon::spSceneExporter sgSceneExporter = sg->CreateSceneExporter();
std::string outputScenePath = std::string("output\\") + std::string("ReductionWithGeomorph") + std::string("_") + std::string(path);
sgSceneExporter->SetExportFilePath(outputScenePath.c_str());
sgSceneExporter->SetScene(sgScene);
// Run scene exporter.
auto exportResult = sgSceneExporter->Run();
if (Simplygon::Failed(exportResult))
{
throw std::exception("Failed to save scene.");
}
}
void ArrayBlend(Simplygon::spRealArray targetArray, Simplygon::spRealArray origArray, Simplygon::spRealArray morphArray, float blend)
{
auto itemCount = targetArray->GetItemCount();
Simplygon::spRealData origData = origArray->GetData();
const float* origDataPtr = origData.Data();
Simplygon::spRealData morphData = morphArray->GetData();
const float* morphDataPtr = morphData.Data();
std::vector<float> targetBuffer(itemCount);
// Morph the geometry
for (auto i = 0U; i < itemCount; ++i)
{
float origValue = origDataPtr[i];
float morphValue = morphDataPtr[i];
float blendResult = morphValue * blend + origValue * (1.0f-blend);
targetBuffer[i] = blendResult;
}
targetArray->SetData(targetBuffer.data(), itemCount);
}
void MorphGeometry(Simplygon::spSceneMesh originalSceneMesh, Simplygon::spSceneMesh morphSceneMesh, Simplygon::spSceneMesh blendSceneMesh, float blend)
{
Simplygon::spGeometryData originalGeometry = originalSceneMesh->GetGeometry();
Simplygon::spGeometryData morphGeometry = morphSceneMesh->GetGeometry();
Simplygon::spGeometryData blendGeometry = blendSceneMesh->GetGeometry();
Simplygon::spRealArray origArray = originalGeometry->GetCoords();
Simplygon::spRealArray morphArray = morphGeometry->GetCoords();
Simplygon::spRealArray targetArray = blendGeometry->GetCoords();
Simplygon::spRidArray origVertexIdsArray = originalGeometry->GetVertexIds();
Simplygon::spRidArray morphVertexIdsArray = morphGeometry->GetVertexIds();
Simplygon::spRidArray targetVertexIdsArray = blendGeometry->GetVertexIds();
auto cornerCount = targetVertexIdsArray->GetItemCount();
auto coordItemCount = targetArray->GetItemCount();
Simplygon::spRidData origVertexIdsData = origVertexIdsArray->GetData();
const Simplygon::rid* origVertexIdsDataPtr = origVertexIdsData.Data();
Simplygon::spRidData morphVertexIdsData = morphVertexIdsArray->GetData();
const Simplygon::rid* morphVertexIdsDataPtr = morphVertexIdsData.Data();
Simplygon::spRidData targetVertexIdsData = targetVertexIdsArray->GetData();
const Simplygon::rid* targetVertexIdsDataPtr = targetVertexIdsData.Data();
Simplygon::spRealData origData = origArray->GetData();
const float* origDataPtr = origData.Data();
Simplygon::spRealData morphData = morphArray->GetData();
const float* morphDataPtr = morphData.Data();
Simplygon::spRealData targetData = targetArray->GetData();
const float* targetDataPtr = targetData.Data();
std::vector<float> targetBuffer(targetDataPtr, targetDataPtr + coordItemCount);
// For each corner:
for (auto c = 0U; c < cornerCount; ++c)
{
auto origVertexId = origVertexIdsDataPtr[c];
auto morphVertexId = morphVertexIdsDataPtr[c];
auto targetVertexId = targetVertexIdsDataPtr[c];
// For each x,z,y value in each coordinate:
for (auto d = 0U; d < 3; ++d)
{
int dInt = (int)d;
float origValue = origDataPtr[origVertexId * 3 + dInt];
float morphValue = morphDataPtr[morphVertexId * 3 + dInt];
float blendResult = morphValue * blend + origValue * (1.0f-blend);
targetBuffer[targetVertexId * 3 + dInt] = blendResult;
}
}
targetArray->SetData(targetBuffer.data(), coordItemCount);
// Morph the UVs
targetArray = blendGeometry->GetTexCoords(0);
origArray = originalGeometry->GetTexCoords(0);
morphArray = morphGeometry->GetTexCoords(0);
ArrayBlend(targetArray, origArray, morphArray, blend);
// Morph the Normals
targetArray = blendGeometry->GetNormals();
origArray = originalGeometry->GetNormals();
morphArray = morphGeometry->GetNormals();
ArrayBlend(targetArray, origArray, morphArray, blend);
}
void RunReductionWithGeomorph(Simplygon::ISimplygon* sg)
{
// Load scene to process.
printf("%s\n", "Load scene to process.");
Simplygon::spScene sgScene = LoadScene(sg, "../../../Assets/SimplygonMan/SimplygonMan.obj");
// Create the reduction processor.
Simplygon::spReductionProcessor sgReductionProcessor = sg->CreateReductionProcessor();
// Select Mesh Nodes
int selectionSetId = sgScene->SelectNodes("ISceneMesh");
// Keep a copy of the original scene to be able to blend between this and the morph geometry.
Simplygon::spScene originalScene = sgScene->NewCopy();
Simplygon::spScene blendScene = sgScene->NewCopy();
sgReductionProcessor->SetScene( sgScene );
Simplygon::spReductionSettings sgReductionSettings = sgReductionProcessor->GetReductionSettings();
// Set reduction target to triangle ratio with a ratio of 50%. Enable geomorph creation and
// disable symmetry quad retriangulator.
sgReductionSettings->SetReductionTargets( Simplygon::EStopCondition::All, true, false, false, false );
sgReductionSettings->SetReductionTargetTriangleRatio( 0.5f );
sgReductionSettings->SetCreateGeomorphGeometry( true );
sgReductionSettings->SetUseSymmetryQuadRetriangulator( false );
Simplygon::spRepairSettings sgRepairSettings = sgReductionProcessor->GetRepairSettings();
// Disable TJunctionRemover.
sgRepairSettings->SetWeldDist( 0.0f );
sgRepairSettings->SetUseTJunctionRemover( false );
Simplygon::spNormalCalculationSettings sgNormalCalculationSettings = sgReductionProcessor->GetNormalCalculationSettings();
// Replace normals.
sgNormalCalculationSettings->SetReplaceNormals( true );
sgNormalCalculationSettings->SetHardEdgeAngle( 60.0f );
// Start the reduction process.
printf("%s\n", "Start the reduction process.");
sgReductionProcessor->RunProcessing();
auto set = sgScene->GetSelectionSetTable()->GetSelectionSet(selectionSetId);
// Selection set to collect geomorph nodes in scene.
Simplygon::spSelectionSet geomorphSelectionSet = sg->CreateSelectionSet();
// Morph the geometry
for (auto blendValue = 0; blendValue < 10; blendValue+=5)
{
auto geometryCount = set->GetItemCount();
// The LOD scene contains morphed geometries, placed as children of their respective reduced
// geometry mesh node.
// The name of a morph mesh node is the same as its parent, with "_geomorph" added.
for (auto geomIndex = 0U; geomIndex < geometryCount; ++geomIndex)
{
auto guid = set->GetItem(geomIndex);
Simplygon::spSceneNode lodSceneNode = sgScene->GetNodeByGUID(guid);
Simplygon::spSceneNode originalSceneNode = originalScene->GetNodeByGUID(guid);
Simplygon::spSceneNode blendSceneNode = blendScene->GetNodeByGUID(guid);
Simplygon::spSceneMesh lodSceneMesh = Simplygon::spSceneMesh::SafeCast(lodSceneNode);
Simplygon::spSceneMesh originalSceneMesh = Simplygon::spSceneMesh::SafeCast(originalSceneNode);
Simplygon::spSceneMesh blendSceneMesh = Simplygon::spSceneMesh::SafeCast(blendSceneNode);
auto childCount = lodSceneNode->GetChildCount();
for (auto childIndex = 0U; childIndex < childCount; ++childIndex)
{
Simplygon::spSceneNode childNode = lodSceneNode->GetChild((int)childIndex);
auto childName = childNode->GetName();
std::string childNodeString = std::string(childName.c_str());
auto name = lodSceneNode->GetName();
std::string geomorphName = std::string("_geomorph");
if (childNodeString.find(geomorphName) != std::string::npos )
{
Simplygon::spSceneMesh morphSceneMesh = Simplygon::spSceneMesh::SafeCast(childNode);
auto morphGUID = morphSceneMesh->GetNodeGUID();
geomorphSelectionSet->AddItem(morphGUID);
MorphGeometry(originalSceneMesh, morphSceneMesh, blendSceneMesh, blendValue*0.1f);
}
}
}
std::string outputName = std::string("Geomorph_BlendedGeometry") + std::string(std::to_string(blendValue).c_str()) + std::string(".obj");
// Save processed scene.
printf("%s\n", "Save processed scene.");
SaveScene(sg, blendScene, outputName.c_str());
}
}
int main()
{
Simplygon::ISimplygon* sg = NULL;
Simplygon::EErrorCodes initval = Simplygon::Initialize( &sg );
if( initval != Simplygon::EErrorCodes::NoError )
{
printf( "Failed to initialize Simplygon: ErrorCode(%d)", (int)initval );
return int(initval);
}
RunReductionWithGeomorph(sg);
Simplygon::Deinitialize(sg);
return 0;
}csharp
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using System;
using System.IO;
using System.Threading.Tasks;
public class Program
{
static Simplygon.spScene LoadScene(Simplygon.ISimplygon sg, string path)
{
// Create scene importer
using Simplygon.spSceneImporter sgSceneImporter = sg.CreateSceneImporter();
sgSceneImporter.SetImportFilePath(path);
// Run scene importer.
var importResult = sgSceneImporter.Run();
if (Simplygon.Simplygon.Failed(importResult))
{
throw new System.Exception("Failed to load scene.");
}
Simplygon.spScene sgScene = sgSceneImporter.GetScene();
return sgScene;
}
static void SaveScene(Simplygon.ISimplygon sg, Simplygon.spScene sgScene, string path)
{
// Create scene exporter.
using Simplygon.spSceneExporter sgSceneExporter = sg.CreateSceneExporter();
string outputScenePath = string.Join("", new string[] { "output\\", "ReductionWithGeomorph", "_", path });
sgSceneExporter.SetExportFilePath(outputScenePath);
sgSceneExporter.SetScene(sgScene);
// Run scene exporter.
var exportResult = sgSceneExporter.Run();
if (Simplygon.Simplygon.Failed(exportResult))
{
throw new System.Exception("Failed to save scene.");
}
}
static void ArrayBlend(Simplygon.spRealArray targetArray, Simplygon.spRealArray origArray, Simplygon.spRealArray morphArray, float blend)
{
var itemCount = targetArray.GetItemCount();
float[] origData;
using (var origData_temp = origArray.GetData()) { origData = origData_temp.ToArray(); }
float[] morphData;
using (var morphData_temp = morphArray.GetData()) { morphData = morphData_temp.ToArray(); }
float[] targetBuffer = new float[(int)(itemCount)];
// Morph the geometry
for (uint i = 0; i < itemCount; ++i)
{
float origValue = origData[(int)(i)];
float morphValue = morphData[(int)(i)];
float blendResult = morphValue * blend + origValue * (1.0f-blend);
targetBuffer[(int)(i)] = blendResult;
}
targetArray.SetData(targetBuffer, (uint)(itemCount));
}
static void MorphGeometry(Simplygon.spSceneMesh originalSceneMesh, Simplygon.spSceneMesh morphSceneMesh, Simplygon.spSceneMesh blendSceneMesh, float blend)
{
Simplygon.spGeometryData originalGeometry = originalSceneMesh.GetGeometry();
Simplygon.spGeometryData morphGeometry = morphSceneMesh.GetGeometry();
Simplygon.spGeometryData blendGeometry = blendSceneMesh.GetGeometry();
Simplygon.spRealArray origArray = originalGeometry.GetCoords();
Simplygon.spRealArray morphArray = morphGeometry.GetCoords();
Simplygon.spRealArray targetArray = blendGeometry.GetCoords();
Simplygon.spRidArray origVertexIdsArray = originalGeometry.GetVertexIds();
Simplygon.spRidArray morphVertexIdsArray = morphGeometry.GetVertexIds();
Simplygon.spRidArray targetVertexIdsArray = blendGeometry.GetVertexIds();
var cornerCount = targetVertexIdsArray.GetItemCount();
var coordItemCount = targetArray.GetItemCount();
int[] origVertexIdsData;
using (var origVertexIdsData_temp = origVertexIdsArray.GetData()) { origVertexIdsData = origVertexIdsData_temp.ToArray(); }
int[] morphVertexIdsData;
using (var morphVertexIdsData_temp = morphVertexIdsArray.GetData()) { morphVertexIdsData = morphVertexIdsData_temp.ToArray(); }
int[] targetVertexIdsData;
using (var targetVertexIdsData_temp = targetVertexIdsArray.GetData()) { targetVertexIdsData = targetVertexIdsData_temp.ToArray(); }
float[] origData;
using (var origData_temp = origArray.GetData()) { origData = origData_temp.ToArray(); }
float[] morphData;
using (var morphData_temp = morphArray.GetData()) { morphData = morphData_temp.ToArray(); }
float[] targetData;
using (var targetData_temp = targetArray.GetData()) { targetData = targetData_temp.ToArray(); }
float[] targetBuffer = (float[])targetData.Clone();
// For each corner:
for (uint c = 0; c < cornerCount; ++c)
{
var origVertexId = origVertexIdsData[(int)(c)];
var morphVertexId = morphVertexIdsData[(int)(c)];
var targetVertexId = targetVertexIdsData[(int)(c)];
// For each x,z,y value in each coordinate:
for (uint d = 0; d < 3; ++d)
{
int dInt = (int)d;
float origValue = origData[(int)(origVertexId * 3 + dInt)];
float morphValue = morphData[(int)(morphVertexId * 3 + dInt)];
float blendResult = morphValue * blend + origValue * (1.0f-blend);
targetBuffer[(int)(targetVertexId * 3 + dInt)] = blendResult;
}
}
targetArray.SetData(targetBuffer, (uint)(coordItemCount));
// Morph the UVs
targetArray = blendGeometry.GetTexCoords(0);
origArray = originalGeometry.GetTexCoords(0);
morphArray = morphGeometry.GetTexCoords(0);
ArrayBlend(targetArray, origArray, morphArray, blend);
// Morph the Normals
targetArray = blendGeometry.GetNormals();
origArray = originalGeometry.GetNormals();
morphArray = morphGeometry.GetNormals();
ArrayBlend(targetArray, origArray, morphArray, blend);
}
static void RunReductionWithGeomorph(Simplygon.ISimplygon sg)
{
// Load scene to process.
Console.WriteLine("Load scene to process.");
Simplygon.spScene sgScene = LoadScene(sg, "../../../Assets/SimplygonMan/SimplygonMan.obj");
// Create the reduction processor.
using Simplygon.spReductionProcessor sgReductionProcessor = sg.CreateReductionProcessor();
// Select Mesh Nodes
int selectionSetId = sgScene.SelectNodes("ISceneMesh");
// Keep a copy of the original scene to be able to blend between this and the morph geometry.
Simplygon.spScene originalScene = sgScene.NewCopy();
Simplygon.spScene blendScene = sgScene.NewCopy();
sgReductionProcessor.SetScene( sgScene );
using Simplygon.spReductionSettings sgReductionSettings = sgReductionProcessor.GetReductionSettings();
// Set reduction target to triangle ratio with a ratio of 50%. Enable geomorph creation and
// disable symmetry quad retriangulator.
sgReductionSettings.SetReductionTargets( Simplygon.EStopCondition.All, true, false, false, false );
sgReductionSettings.SetReductionTargetTriangleRatio( 0.5f );
sgReductionSettings.SetCreateGeomorphGeometry( true );
sgReductionSettings.SetUseSymmetryQuadRetriangulator( false );
using Simplygon.spRepairSettings sgRepairSettings = sgReductionProcessor.GetRepairSettings();
// Disable TJunctionRemover.
sgRepairSettings.SetWeldDist( 0.0f );
sgRepairSettings.SetUseTJunctionRemover( false );
using Simplygon.spNormalCalculationSettings sgNormalCalculationSettings = sgReductionProcessor.GetNormalCalculationSettings();
// Replace normals.
sgNormalCalculationSettings.SetReplaceNormals( true );
sgNormalCalculationSettings.SetHardEdgeAngle( 60.0f );
// Start the reduction process.
Console.WriteLine("Start the reduction process.");
sgReductionProcessor.RunProcessing();
var set = sgScene.GetSelectionSetTable().GetSelectionSet(selectionSetId);
// Selection set to collect geomorph nodes in scene.
using Simplygon.spSelectionSet geomorphSelectionSet = sg.CreateSelectionSet();
// Morph the geometry
for (uint blendValue = 0; blendValue < 10; blendValue+=5)
{
var geometryCount = set.GetItemCount();
// The LOD scene contains morphed geometries, placed as children of their respective reduced
// geometry mesh node.
// The name of a morph mesh node is the same as its parent, with "_geomorph" added.
for (uint geomIndex = 0; geomIndex < geometryCount; ++geomIndex)
{
var guid = set.GetItem(geomIndex);
Simplygon.spSceneNode lodSceneNode = sgScene.GetNodeByGUID(guid);
Simplygon.spSceneNode originalSceneNode = originalScene.GetNodeByGUID(guid);
Simplygon.spSceneNode blendSceneNode = blendScene.GetNodeByGUID(guid);
Simplygon.spSceneMesh lodSceneMesh = Simplygon.spSceneMesh.SafeCast(lodSceneNode);
Simplygon.spSceneMesh originalSceneMesh = Simplygon.spSceneMesh.SafeCast(originalSceneNode);
Simplygon.spSceneMesh blendSceneMesh = Simplygon.spSceneMesh.SafeCast(blendSceneNode);
var childCount = lodSceneNode.GetChildCount();
for (uint childIndex = 0; childIndex < childCount; ++childIndex)
{
Simplygon.spSceneNode childNode = lodSceneNode.GetChild((int)childIndex);
var childName = childNode.GetName();
string childNodeString = string.Join("", new string[] { childName });
var name = lodSceneNode.GetName();
string geomorphName = string.Join("", new string[] { "_geomorph" });
if (childNodeString.Contains(geomorphName) )
{
Simplygon.spSceneMesh morphSceneMesh = Simplygon.spSceneMesh.SafeCast(childNode);
var morphGUID = morphSceneMesh.GetNodeGUID();
geomorphSelectionSet.AddItem(morphGUID);
MorphGeometry(originalSceneMesh, morphSceneMesh, blendSceneMesh, blendValue*0.1f);
}
}
}
string outputName = string.Join("", new string[] { "Geomorph_BlendedGeometry", blendValue.ToString(), ".obj" });
// Save processed scene.
Console.WriteLine("Save processed scene.");
SaveScene(sg, blendScene, outputName);
}
}
static int Main(string[] args)
{
using var sg = Simplygon.Loader.InitSimplygon(out var errorCode, out var errorMessage);
if (errorCode != Simplygon.EErrorCodes.NoError)
{
Console.WriteLine( $"Failed to initialize Simplygon: ErrorCode({(int)errorCode}) {errorMessage}" );
return (int)errorCode;
}
RunReductionWithGeomorph(sg);
return 0;
}
}python
# 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 simplygon10 import simplygon_loader
from simplygon10 import Simplygon
def LoadScene(sg: Simplygon.ISimplygon, path: str):
# Create scene importer
sgSceneImporter = sg.CreateSceneImporter()
sgSceneImporter.SetImportFilePath(path)
# Run scene importer.
importResult = sgSceneImporter.Run()
if Simplygon.Failed(importResult):
raise Exception('Failed to load scene.')
sgScene = sgSceneImporter.GetScene()
return sgScene
def SaveScene(sg: Simplygon.ISimplygon, sgScene: Simplygon.spScene, path: str):
# Create scene exporter.
sgSceneExporter = sg.CreateSceneExporter()
outputScenePath = ''.join(['output\\', 'ReductionWithGeomorph', '_', path])
sgSceneExporter.SetExportFilePath(outputScenePath)
sgSceneExporter.SetScene(sgScene)
# Run scene exporter.
exportResult = sgSceneExporter.Run()
if Simplygon.Failed(exportResult):
raise Exception('Failed to save scene.')
def ArrayBlend(targetArray: Simplygon.spRealArray, origArray: Simplygon.spRealArray, morphArray: Simplygon.spRealArray, blend):
itemCount = targetArray.GetItemCount()
origData = origArray.GetData()
morphData = morphArray.GetData()
targetBuffer = [0.0] * itemCount
# Morph the geometry
for i in range(itemCount):
origValue = origData[i]
morphValue = morphData[i]
blendResult = morphValue * blend + origValue * (1.0-blend)
targetBuffer[i] = blendResult
targetArray.SetData(targetBuffer, itemCount)
def MorphGeometry(originalSceneMesh: Simplygon.spSceneMesh, morphSceneMesh: Simplygon.spSceneMesh, blendSceneMesh: Simplygon.spSceneMesh, blend):
originalGeometry = originalSceneMesh.GetGeometry()
morphGeometry = morphSceneMesh.GetGeometry()
blendGeometry = blendSceneMesh.GetGeometry()
origArray = originalGeometry.GetCoords()
morphArray = morphGeometry.GetCoords()
targetArray = blendGeometry.GetCoords()
origVertexIdsArray = originalGeometry.GetVertexIds()
morphVertexIdsArray = morphGeometry.GetVertexIds()
targetVertexIdsArray = blendGeometry.GetVertexIds()
cornerCount = targetVertexIdsArray.GetItemCount()
coordItemCount = targetArray.GetItemCount()
origVertexIdsData = origVertexIdsArray.GetData()
morphVertexIdsData = morphVertexIdsArray.GetData()
targetVertexIdsData = targetVertexIdsArray.GetData()
origData = origArray.GetData()
morphData = morphArray.GetData()
targetData = targetArray.GetData()
targetBuffer = list(targetData)
# For each corner:
for c in range(cornerCount):
origVertexId = origVertexIdsData[c]
morphVertexId = morphVertexIdsData[c]
targetVertexId = targetVertexIdsData[c]
# For each x,z,y value in each coordinate:
for d in range(3):
dInt = d
origValue = origData[origVertexId * 3 + dInt]
morphValue = morphData[morphVertexId * 3 + dInt]
blendResult = morphValue * blend + origValue * (1.0-blend)
targetBuffer[targetVertexId * 3 + dInt] = blendResult
targetArray.SetData(targetBuffer, coordItemCount)
# Morph the UVs
targetArray = blendGeometry.GetTexCoords(0)
origArray = originalGeometry.GetTexCoords(0)
morphArray = morphGeometry.GetTexCoords(0)
ArrayBlend(targetArray, origArray, morphArray, blend)
# Morph the Normals
targetArray = blendGeometry.GetNormals()
origArray = originalGeometry.GetNormals()
morphArray = morphGeometry.GetNormals()
ArrayBlend(targetArray, origArray, morphArray, blend)
def RunReductionWithGeomorph(sg: Simplygon.ISimplygon):
# Load scene to process.
print("Load scene to process.")
sgScene = LoadScene(sg, '../../../Assets/SimplygonMan/SimplygonMan.obj')
# Create the reduction processor.
sgReductionProcessor = sg.CreateReductionProcessor()
# Select Mesh Nodes
selectionSetId = sgScene.SelectNodes('ISceneMesh')
# Keep a copy of the original scene to be able to blend between this and the morph geometry.
originalScene = sgScene.NewCopy()
blendScene = sgScene.NewCopy()
sgReductionProcessor.SetScene( sgScene )
sgReductionSettings = sgReductionProcessor.GetReductionSettings()
# Set reduction target to triangle ratio with a ratio of 50%. Enable geomorph creation and
# disable symmetry quad retriangulator.
sgReductionSettings.SetReductionTargets( Simplygon.EStopCondition_All, True, False, False, False )
sgReductionSettings.SetReductionTargetTriangleRatio( 0.5 )
sgReductionSettings.SetCreateGeomorphGeometry( True )
sgReductionSettings.SetUseSymmetryQuadRetriangulator( False )
sgRepairSettings = sgReductionProcessor.GetRepairSettings()
# Disable TJunctionRemover.
sgRepairSettings.SetWeldDist( 0.0 )
sgRepairSettings.SetUseTJunctionRemover( False )
sgNormalCalculationSettings = sgReductionProcessor.GetNormalCalculationSettings()
# Replace normals.
sgNormalCalculationSettings.SetReplaceNormals( True )
sgNormalCalculationSettings.SetHardEdgeAngle( 60.0 )
# Start the reduction process.
print("Start the reduction process.")
sgReductionProcessor.RunProcessing()
set = sgScene.GetSelectionSetTable().GetSelectionSet(selectionSetId)
# Selection set to collect geomorph nodes in scene.
geomorphSelectionSet = sg.CreateSelectionSet()
# Morph the geometry
for blendValue in range(0,10,5):
geometryCount = set.GetItemCount()
# The LOD scene contains morphed geometries, placed as children of their respective reduced
# geometry mesh node.
# The name of a morph mesh node is the same as its parent, with "_geomorph" added.
for geomIndex in range(geometryCount):
guid = set.GetItem(geomIndex)
lodSceneNode = sgScene.GetNodeByGUID(guid)
originalSceneNode = originalScene.GetNodeByGUID(guid)
blendSceneNode = blendScene.GetNodeByGUID(guid)
lodSceneMesh = Simplygon.spSceneMesh.SafeCast(lodSceneNode)
originalSceneMesh = Simplygon.spSceneMesh.SafeCast(originalSceneNode)
blendSceneMesh = Simplygon.spSceneMesh.SafeCast(blendSceneNode)
childCount = lodSceneNode.GetChildCount()
for childIndex in range(childCount):
childNode = lodSceneNode.GetChild(childIndex)
childName = childNode.GetName()
childNodeString = ''.join([childName])
name = lodSceneNode.GetName()
geomorphName = ''.join(['_geomorph'])
if geomorphName in childNodeString:
morphSceneMesh = Simplygon.spSceneMesh.SafeCast(childNode)
morphGUID = morphSceneMesh.GetNodeGUID()
geomorphSelectionSet.AddItem(morphGUID)
MorphGeometry(originalSceneMesh, morphSceneMesh, blendSceneMesh, blendValue*0.1)
outputName = ''.join(['Geomorph_BlendedGeometry', str(blendValue), '.obj'])
# Save processed scene.
print("Save processed scene.")
SaveScene(sg, blendScene, outputName)
if __name__ == '__main__':
sg = simplygon_loader.init_simplygon()
if sg is None:
exit(Simplygon.GetLastInitializationError())
RunReductionWithGeomorph(sg)
sg = None
gc.collect()