Scripting xNormal with Python
13/05/2012
In the process of building a rather elaborate toolchain I decided it was about time I developed a proper scripting tool for xNormal. I developed a simple wrapper in Python as most of my toolchain was offline, outside of some application, and running python already.
xNormal provides a pretty decent automation interface in the form of supplying it with an XML configuration file. These files are also used as save files in the application to store the current settings. So the interface was a case of generating these configuration files per run and supplying them to the application.
The result is a single script which can be found on github or downloaded via the package index at PyPI.
To copy from the README:
Basic Usage
The below generates a normal map and ambient occlusion map for two piano meshes.
import xNormal xNormal.run("piano_high.obj", "piano_low.obj", "piano.png", width=256, height=256, gen_normals = True, gen_ao = True)
Extended Usage 1
The belows shows some more features. First the path is set. By default the wrapper assumes xNormal.exe is on the PATH. Secondly it generates a normal map with a switched coordinate system and an ao map with fewer rays and jitter. It also generates a convexity map. Finally it stores the errorcode of xNormal in case of something going wrong.
For a full list of options have a look in the source code where they are listed and easy to see.
import xNormal xNormal.path = "C:\\Program Files (x86)\\Santiago Orgaz\\xNormal 3.17.13\\x64\\xNormal.exe" retcode = xNormal.run("piano_high.obj", "piano_low.obj", "piano.png", width = 256, height = 256, gen_normals = True, normals_x = "+X", normals_y = "-Z", normals_z = "+Y", gen_ao = True, ao_rays = 64, ao_jitter = True, gen_convexity = True, convexity_scale = 0.75)
Extended Usage 2
Configuration files can be generated and saved for later use.
To build a configuration file xNormal.config
must be supplied with a list of high mesh options, a list of low mesh options and generation options.
import xNormal high_config = xNormal.high_mesh_options("piano_high.obj", scale = 2.0) low_config = xNormal.low_mesh_options("piano_low.obj", scale = 2.0) generation_config = xNormal.generation_options("piano.png", gen_normals = True) config = xNormal.config([high_config], [low_config], generation_config) f = open("later.xml", 'w') f.write(config) f.close()