# 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 RunRemeshingWithMaterialCasting(sg: Simplygon.ISimplygon):
    sgSceneImporter = sg.CreateSceneImporter()
    sgSceneImporter.SetImportFilePath( "../Assets/RiggedSimplygonMan/RiggedSimplygonMan.fbx" )
    if not sgSceneImporter.RunImport():
        raise Exception("Failed to load RiggedSimplygonMan/RiggedSimplygonMan.fbx.")
    sgScene = sgSceneImporter.GetScene()

    # Create the remeshing pipeline. 
    sgRemeshingPipeline = sg.CreateRemeshingPipeline()

    sgRemeshingSettings = sgRemeshingPipeline.GetRemeshingSettings()
    sgMappingImageSettings = sgRemeshingPipeline.GetMappingImageSettings()

    # Set on-screen size target for remeshing. 
    sgRemeshingSettings.SetOnScreenSize( 300 )

    # Generates a mapping image which is used after the remeshing to cast new materials to the new 
    # remeshed object. 
    sgMappingImageSettings.SetGenerateMappingImage( True )
    sgMappingImageSettings.SetApplyNewMaterialIds( True )
    sgMappingImageSettings.SetGenerateTangents( True )
    sgMappingImageSettings.SetUseFullRetexturing( True )

    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 )

    # Add diffuse material caster to pipeline. 
    sgDiffuseCaster = sg.CreateColorCaster()
    sgDiffuseCasterSettings = sgDiffuseCaster.GetColorCasterSettings()
    sgDiffuseCasterSettings.SetMaterialChannel( "Diffuse" )
    sgDiffuseCasterSettings.SetOutputImageFileFormat( Simplygon.EImageOutputFormat_PNG )

    sgRemeshingPipeline.AddMaterialCaster( sgDiffuseCaster, 0 )

    # Add normals material caster to pipeline. 
    sgNormalsCaster = sg.CreateNormalCaster()
    sgNormalsCasterSettings = sgNormalsCaster.GetNormalCasterSettings()
    sgNormalsCasterSettings.SetMaterialChannel( "Normals" )
    sgNormalsCasterSettings.SetGenerateTangentSpaceNormals( True )
    sgNormalsCasterSettings.SetOutputImageFileFormat( Simplygon.EImageOutputFormat_PNG )

    sgRemeshingPipeline.AddMaterialCaster( sgNormalsCaster, 0 )

    # Start the remeshing pipeline. 
    sgRemeshingPipeline.RunScene(sgScene, Simplygon.EPipelineRunMode_RunInThisProcess)

    # Get the processed scene. 
    sgProcessedScene = sgRemeshingPipeline.GetProcessedScene()

    sgSceneExporter = sg.CreateSceneExporter()
    sgSceneExporter.SetScene(sgProcessedScene)
    sgSceneExporter.SetExportFilePath( "RemeshingOutput.fbx" )
    if not sgSceneExporter.RunExport():
        raise Exception("Failed to save RemeshingOutput.fbx.")


if __name__ == '__main__':
    sg = simplygon_loader.init_simplygon()

    RunRemeshingWithMaterialCasting(sg)

    sg = None
    gc.collect()

