Documentation

Support

Asset Transformer SDK


User Manual

Python API

C# API

Changelog

Discussions

Asset Transformer SDK

Optimization guidelines

Learn how to optimize CAD files for real-time 3D experiences.
Read time 4 minutesLast updated a day ago

Why optimize CAD files?

CAD models are created for design and manufacturing, not real-time visualization. Real-time applications aim for a stable frame rate — often 60 frames per second (FPS) for smooth interaction. If your model is too heavy, the GPU spends too much time processing geometry and materials, causing FPS to drop. This can happen for two main reasons:
  • Polygon count – Too many triangles (polygons) in the meshes, increasing GPU workload.
  • Draw calls – CPU-to-GPU commands to render each mesh/material, creating bottlenecks in rendering.
Optimizing these will improve frame rate, reduce load times, and make your models usable on a wider range of devices.

1. Reduce polygon count

Polygon count refers to the number of triangles that make up your 3D geometry. More polygons mean more GPU work per frame.

Repair meshes first

Always repair meshes before decimation to fix topology issues that can cause problems during optimization.
roots = [root]# Repair mesh geometry before optimizationtolerance = 0.1 # Adjust based on model unitsalgo.repairMesh(roots, tolerance=tolerance, crackNonManifold=True, orient=False)

Decimate meshes

The most common way to lower polygon count is mesh decimation, which simplifies geometry while preserving shape.

Remove occluded geometries

If the polygon count is still too high after decimation, the next step is to eliminate geometry that will never be seen in the final render. This processing proves particularly efficient on these models:
  • Models that have internal parts
  • Models that have been designed as solids
  • Models that have been designed using CAD software
Example: Complex assemblies often contain internal bolts, wiring, or invisible surfaces that don't need to be rendered.

Retopologize meshes

If the polygon count is still too high after decimation and occluded geometries removal, restart from the original file and try remeshing your model. Retopology rebuilds a mesh with a cleaner, lower-poly surface. This technique is especially useful for creating Levels of Detail (LODs).

2. Reduce the number of draw calls

A draw call is a command that is sent by the CPU to the GPU to draw a mesh with a specific material on screen. Too many draw calls can slow rendering even if polygon count is low. The more time is spent on draw calls, the less time is left for the GPU to execute these commands during the remaining frame time. A good strategy is to reduce the number of draw calls or to group commands into a single batch command. Reduce the draw call count by reducing the number of unique meshes and materials.

Reduce the number of unique meshes

Repair instances

A mesh can be instantiated several times in a scene. Depending on your renderer, all instances of a mesh that share the same material will be drawn with a single draw call. When importing a CAD file, Asset Transformer reads instancing information so that identical meshes are not unnecessarily duplicated. However, it can happen that the original file was not designed using instances, or that certain meshes slightly differ from one another, resulting in one draw call per mesh. In these cases, you can recreate instances by detecting and grouping similar meshes based on chosen criteria.

Merge meshes

If the number of draw calls is still too high after re-creating mesh instances, we recommend that you simplify the product structure (hierarchy) and merge the meshes together. Merging is the easiest way to reduce the number of draw calls, but has two disadvantages:
  • Merging flattens the hierarchy. You can choose to merge models at specific levels, to merge only the subassemblies that represent a set.
  • Merging can prevent culling (occlusion/frustrum) to work properly. See the merge by regions approach for more information.
  • Merging destroys the instances of a same mesh, increasing the memory footprint and the total number of triangles that will be drawn.
For all these reasons, merging can actually deteriorate performances and increase the input file size.

Reduce the number of materials

If the number of draw calls is still too high after reducing the number of unique meshes, you can try lowering the number of different materials.

Delete duplicated materials

Due to design complexity, CAD files often contain duplicated materials. Merge duplicate images and materials to automatically detect and remove them.
# Merge duplicate images (textures)scene.mergeImages()# Merge duplicate materialsscene.mergeMaterials()

Combine materials

If the number of materials is still too high, an option is to combine them into a single material. Check the Bake Materials documentation for more information.

Platform-specific recommendations

Desktop (Desktop)
  • Target: 10-100M triangles per scene, < 10000 draw calls
  • Can afford: Higher polygon counts, more materials
Mobile
  • Target: 100K-500K triangles per scene, < 1000 draw calls
  • Critical: Stay within vertex limits, minimize texture memory
VR
  • Target: 500K-2M triangles per scene, < 1000 draw calls (need to render twice)
  • Focus on: Balanced decimation, occlusion removal, draw call reduction
  • Critical: Maintain 90+ FPS, minimize vertex shader complexity
WebGL
  • Target: 100K-1M triangles per scene, < 200 draw calls
  • Focus on: Decimation, material reduction, small file size
  • Critical: Minimize memory usage, fast loading

Script

RATIO = 25 # Reduce the number of triangles by 75%root = scene.getRoot()# Reduce number of draw callsalgo.convertSimilarPartOccurrencesToInstancesFast([root], 0.98, 0.98, ignoreSymmetry=True)scene.mergeImages()scene.mergeMaterials()# Reduce the polygon countalgo.repairMesh([root], tolerance=0.1, crackNonManifold=True, orient=False)algo.removeOccludedGeometries([root], level=pxz.algo.SelectionLevel.Polygons, resolution=512, sphereCount=256, adjacencyDepth=1, onHemisphereOnly=False) # Requires GPUalgo.decimateTarget([root], ["ratio", RATIO])