Blender for XR content automation

Raju K
XRPractices
Published in
2 min readNov 27, 2021

XR (AR/VR/MR) experiences are influenced by the 3D content. Since most of the XR devices are mobile based units, the capability to chew 3D models at runtime and produce required FPS is a challenging job for the hardware.

The 3D content for XR comes mostly from traditional CAD models which are produced either for manufacturing needs or for high quality rendering needs. In both cases, the model sizes (points, triangles) are huge and may not be readily usable in XR as they may not produce required FPS if they are used as is.

In order to bring optimal XR experience, the 3D content should be made optimal too. Blender with its Python API combined with a command line mode execution environment allows us to author the pre-processing of 3D content for use in XR in an automated fashion. To execute the automation in any pipeline,

<path_to_blender_executable> --background --python <path_to_python_automation> <args ...>

Example in my case,

"C:\Program Files\Blender Foundation\Blender 2.93\Blender.exe" --background --python decimator.py "C:\Work\Models\statue.fbx"

In this article, we discuss about writing one such automation. The goal of the automation is to optimize the mesh in the input model and produce an optimized version of the model for XR use.

Key Steps:

  1. Initialize the class and import the incoming fbx into the scene
class Decimator:
def __init__(self, fbx_file):
bpy.ops.import_scene.fbx(filepath=fbx_file)
mesh = bpy.context.selected_objects[0]

2. Decimate the mesh. For this example, a target face count of 1000 is used.

def simplifymesh(self, mesh):  
bpy.context.view_layer.objects.active = mesh
mod = mesh.modifiers.new(name='Decimate', type='DECIMATE')
bpy.context.object.modifiers['Decimate'].use_collapse_triangulate = True
nfaces = len(mesh.data.polygons)
if nfaces > 1000:
ratio = target_faces / float(nfaces)
mod.ratio = float('%s' % ('%.6g' % (ratio)))
print('faces: ', mod.face_count, mod.ratio)
bpy.ops.object.modifier_apply(modifier=mod.name)

3. Export the mesh

def export_fbx(self, mesh, fbx_file):        
outpath = os.path.dirname(fbx_file)
(outfile, ext) = os.path.splitext(fbx_file)
if not os.path.isdir(outpath): os.makedirs(outpath)
output_fbx = os.path.join(outpath, outfile + "_decimated.fbx")
print('EXPORTING', output_fbx)
bpy.ops.object.select_all(action='DESELECT')
mesh.select_set(state=True)
bpy.ops.export_scene.fbx(filepath=output_fbx)

A Sample conversion of an Angle Statue downloaded from Sketchfab using the automation discussed in this article

Left (Original Mesh), Right (Optimized Mesh)
Left (Original Mesh), Right (Optimized Mesh for XR)

A complete version of this automation as follows

--

--

Raju K
XRPractices

Innovator | XR | AR | VR| Robotics Enthusiast | Thoughtworks