Getting started with quad reduction in Maya
Written by Jesper Tingvall, Product Expert, Simplygon
Disclaimer: The code in this post is written using version 10.4.117.0 of Simplygon and Maya 2022.5. 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
In this blog we will look at how to use the quad reducer in Maya for character optimization. We'll look at both how to use it from the user interface but also from scripting.
Prerequisites
This example will use the Simplygon integration in Maya, but the same concepts can be applied to all other integrations with quad optimization support.
Problem to solve
We have a skinned character asset made from quads which we want to optimize while keeping the quad topology.
Solution
The solution is to use Simplygon's quad reducer. This is accessible from Simplygon's Maya plug-in. Before you proceed, ensure that you have Simplygon installed and the Maya plug-in has been activated and loaded.
Basic reduction
The quad reducer can be accessed from the Simplygon Window. To add a quad reduction pipeline, click Add LOD Component → Template → Basic → Quad reduction.
Now it is time to choose target and stop condition. You can choose to target a specific polygon count, polygon ratio, on screen size or max deviation. We strongly suggest using on screen size or max deviation as this is a requirement for models containing both quads and triangles to be processed correctly. For a deeper explanation on working with mixed assets and triangles, see the documentation. We go with an on screen size of 500.
After optimization we get the following result, we can see that the model has kept its quad topology.


Quad reduction in Maya Python scripting
It is also possible to use quad reducer through script. If you are familiar with how our Python API integrates into Maya you will recognize it. There is one important thing to keep in mind, we need to specify that we should export and import from Maya to Simplygon in QuadMode. We do this by setting QuadMode = True
. If we do not do this then our model will become triangulated.
This is how to export a selection from Maya into Simplygon while keeping quads with the Simplygon command.
def export_selection(sg):
"""Export the current selected objects into a Simplygon scene with quads."""
cmds.Simplygon(exp = tmp_file, QuadMode = True)
scene = sg.CreateScene()
scene.LoadFromFile(tmp_file)
return scene
Once we have the scene exported from Maya we can process it with a QuadReductionPipeline
. With SetReductionTargets
we can specify which reduction target to use. We'll use same as before, on screen size. This can be set with SetReductionTargetOnScreenSize
.
def reduce_quads(sg, scene, screen_size):
"""Reduce quads in scene for specific screen_size."""
quad_pipeline = sg.CreateQuadReductionPipeline()
quad_reduction_settings = quad_pipeline.GetQuadReductionSettings()
quad_reduction_settings.SetReductionTargetOnScreenSize( screen_size)
quad_reduction_settings.SetReductionTargets( Simplygon.EStopCondition_Any, False, False, False, True )
quad_pipeline.RunScene( scene, Simplygon.EPipelineRunMode_RunInThisProcess )
We also need to specify QuadMode = True
during import into Maya.
def import_results(scene):
"""Import the Simplygon scene into Maya."""
scene.SaveToFile(tmp_file)
cmds.Simplygon(imp=tmp_file, lma=True, QuadMode = True)
After import we get the same result as when using the UI.
Result
Let us look closer at the face of our character asset so we can see the result. We can see some slight differences but have to keep in mind that the asset are optimized for being rendered at 500 pixels, so we are looking at it closer then expected.


Here is the wireframe. The quad reducer works by removing entire quad strips, how well it performs depends a lot on the quad topology of the model.


If we look at the triangle count, we can see that we have removed 6k triangles.
Asset | Triangle count |
---|---|
Original asset | 23 k |
On Screen Size = 500 | 17 k |
As we wrote in our previous blog post Character optimization with quad reduction: If retaining quads and mesh structure is not a priority, the standard triangle reducer will often have more freedom to reach low triangle counts at lower geometric errors. If keeping the quad structure is important then the quad reducer is the tool to use.
Next steps
After you've done some experimentation with the quad reducer it can be a good idea to start thinking about how you are going to automate your asset pipeline. You can also look into how to optimize assets with mixed pipelines, for example using the quad reducer for first LOD levels, and then switch over to triangle reducer for the faraway ones.
Complete script
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT license.
from simplygon10 import simplygon_loader
from simplygon10 import Simplygon
import maya.cmds as cmds
tmp_file = "c:/Temp/export.sb"
screen_size = 500
def export_selection(sg):
"""Export the current selected objects into a Simplygon scene with quads."""
cmds.Simplygon(exp = tmp_file, QuadMode = True)
scene = sg.CreateScene()
scene.LoadFromFile(tmp_file)
return scene
def import_results(scene):
"""Import the Simplygon scene into Maya."""
scene.SaveToFile(tmp_file)
cmds.Simplygon(imp=tmp_file, lma=True, QuadMode = True)
def reduce_quads(sg, scene, screen_size):
"""Reduce quads in scene for specific screen_size."""
quad_pipeline = sg.CreateQuadReductionPipeline()
quad_reduction_settings = quad_pipeline.GetQuadReductionSettings()
quad_reduction_settings.SetReductionTargetOnScreenSize( screen_size)
quad_reduction_settings.SetReductionTargets( Simplygon.EStopCondition_Any, False, False, False, True )
quad_pipeline.RunScene( scene, Simplygon.EPipelineRunMode_RunInThisProcess )
def main():
sg = simplygon_loader.init_simplygon()
# Set tangent space for Maya
sg.SetGlobalDefaultTangentCalculatorTypeSetting(Simplygon.ETangentSpaceMethod_MikkTSpace)
# Export from Maya to Simplygon
scene = export_selection(sg)
# Reduce quads
reduce_quads(sg, scene, screen_size)
# Export to Maya
import_results(scene)
if __name__== "__main__":
main()