A simple Python remeshing

Disclaimer: The code in this post is written on version 9.1 of Simplygon. If you encounter this post at a later stage, some of the API calls might have changed. However, the core concepts should still remain valid.

Introduction

This post will give you a simple starting point for a remeshing script. We'll show how to turn an glb asset, colorized by material parameters, into a textured proxy.

The asset

We are going to use these merged spheres as an example asset. They have different materials, and the diffuse color is a parameter rather than a texture. Spheres

The remeshing pipeline script

Starting point

As always, let's use this same template as a starting point for our script.

from simplygon import simplygon_loader
from simplygon import Simplygon

def main():
    sg = simplygon_loader.init_simplygon()
    process_file(sg, "spheres.glb", "output.glb")
    del sg

if __name__== "__main__":
    main()

Nothing fancy here. The process_file function will do the bulk of the work.

Process file

Our goal with the process function is that it should take the incoming asset file, run a remeshing processing where a diffuse and a normal map is created. Finally, it should write out the result to the output file.

Let's start by importing the incoming asset.

def process_file(sg, asset_file, output_file):
    # Load the asset we want to process
    scene_importer = sg.CreateSceneImporter()
    scene_importer.SetImportFilePath(asset_file)
    if scene_importer.RunImport():
        scene = scene_importer.GetScene()

Now that we have a scene, let's create a remeshing pipeline that we can apply to it.

remeshing_pipeline = sg.CreateRemeshingPipeline()
remesher_settings = remeshing_pipeline.GetRemeshingSettings()
remesher_settings.SetOnScreenSize(300)        

This sets up the pipeline to create a really coarse representation asset.

Material casting

We need to add the desired material casters to the pipeline as well. Before we do that, let's set up the texture size for the output asset. How about 512x512?

mapping_image_settings = remeshing_pipeline.GetMappingImageSettings()
material_settings = mapping_image_settings.GetOutputMaterialSettings(0)
material_settings.SetTextureWidth(512)
material_settings.SetTextureHeight(512)

Time for the material casters. First we will add the material caster for the diffuse channel.

caster = sg.CreateColorCaster()
caster_settings = caster.GetColorCasterSettings()
caster_settings.SetMaterialChannel(Simplygon.SG_MATERIAL_CHANNEL_BASECOLOR) 
remeshing_pipeline.AddMaterialCaster( caster, 0 )

Since our input is a glb file, the channel name for the diffuse color is Basecolor, which is the value of the constant SG_MATERIAL_CHANNEL_BASECOLOR.

When remeshing assets, it's typically a good idea to also generate a normal map as that will allow Simplygon to transfer geometrical details that are removed into that map. So, let's do that.

caster = sg.CreateNormalCaster()
caster_settings = caster.GetNormalCasterSettings()
caster_settings.SetGenerateTangentSpaceNormals(True)
caster_settings.SetMaterialChannel(Simplygon.SG_MATERIAL_CHANNEL_NORMALS) 
remeshing_pipeline.AddMaterialCaster( caster, 0 )

Metalness and Roughness

If you want the representation to be as close as possible and are willing to sacrifice a bit extra texture memory, you can add casters for metalness and roughness as well. They are added the same way as the caster for the diffuse color, like this:

caster = sg.CreateColorCaster()
caster_settings = caster.GetColorCasterSettings()
caster_settings.SetMaterialChannel(Simplygon.SG_MATERIAL_CHANNEL_METALNESS) 
remeshing_pipeline.AddMaterialCaster( caster, 0 )

caster = sg.CreateColorCaster()
caster_settings = caster.GetColorCasterSettings()
caster_settings.SetMaterialChannel(Simplygon.SG_MATERIAL_CHANNEL_ROUGHNESS) 
remeshing_pipeline.AddMaterialCaster( caster, 0 )

Running the pipeline

Everything is in place for us to run the remeshing process and output the results. Here's the code that does that.

remeshing_pipeline.RunScene(scene, Simplygon.EPipelineRunMode_RunInThisProcess)        
scene_exporter = sg.CreateSceneExporter()
scene_exporter.SetExportFilePath(output_file)
scene_exporter.SetScene(scene)
scene_exporter.RunExport()

The results

Running the script on our example asset will produce the following output. Remesh output

The produced texture now contains the colors from the original materials.

Remeshed Texture

This is all you need to create your first simple remeshing pipeline.

The complete script

# Copyright (c) Microsoft Corporation. 
# Licensed under the MIT license. 
 
from simplygon import simplygon_loader
from simplygon import Simplygon

def process_file(sg, asset_file, output_file):
    # Load the asset we want to process
    scene_importer = sg.CreateSceneImporter()
    scene_importer.SetImportFilePath(asset_file)
    if scene_importer.RunImport():
        scene = scene_importer.GetScene()
        remeshing_pipeline = sg.CreateRemeshingPipeline()
        remesher_settings = remeshing_pipeline.GetRemeshingSettings()
        remesher_settings.SetOnScreenSize(300)        
        mapping_image_settings = remeshing_pipeline.GetMappingImageSettings()
        material_settings = mapping_image_settings.GetOutputMaterialSettings(0)
        material_settings.SetTextureWidth(1024)
        material_settings.SetTextureHeight(1024)

        caster = sg.CreateColorCaster()
        caster_settings = caster.GetColorCasterSettings()
        caster_settings.SetMaterialChannel(Simplygon.SG_MATERIAL_CHANNEL_BASECOLOR) 
        remeshing_pipeline.AddMaterialCaster( caster, 0 )

        caster = sg.CreateColorCaster()
        caster_settings = caster.GetColorCasterSettings()
        caster_settings.SetMaterialChannel(Simplygon.SG_MATERIAL_CHANNEL_METALNESS) 
        remeshing_pipeline.AddMaterialCaster( caster, 0 )

        caster = sg.CreateColorCaster()
        caster_settings = caster.GetColorCasterSettings()
        caster_settings.SetMaterialChannel(Simplygon.SG_MATERIAL_CHANNEL_ROUGHNESS) 
        remeshing_pipeline.AddMaterialCaster( caster, 0 )

        caster = sg.CreateNormalCaster()
        caster_settings = caster.GetNormalCasterSettings()
        caster_settings.SetGenerateTangentSpaceNormals(True)
        caster_settings.SetMaterialChannel(Simplygon.SG_MATERIAL_CHANNEL_NORMALS) 
        remeshing_pipeline.AddMaterialCaster( caster, 0 )

        print("Running remeshing process...")
        remeshing_pipeline.RunScene(scene, Simplygon.EPipelineRunMode_RunInThisProcess)        
        scene_exporter = sg.CreateSceneExporter()
        scene_exporter.SetExportFilePath(output_file)
        scene_exporter.SetScene(scene)
        scene_exporter.RunExport()


def main():
    sg = simplygon_loader.init_simplygon()
    print(sg.GetVersion())
    process_file(sg, "spheres.glb", "remeshed_spheres.glb")
    del sg

if __name__== "__main__":
    main()
⇐ Back to all posts

Request 30-days free evaluation license

*
*
*
*
Industry
*

Request 30-days free evaluation license

*
*
*
*
Industry
*