Convert the axes of a scene using bpy_extras.io_utils.axis_conversion
.
To convert such that both objects and their data, mesh in this case follow the new axis conversion, need to apply the conversion to both the object and its mesh data.
Image below shows Suzanne in blender default of Z up and -Y forward. With some translation, rotation and scale. Camera and Lamp are from default file.
Lets change the axis
As you pointed out in your answer the axis_conversion
to Z forward Y up is a matter of rotating the axes -90 degrees about X.
>> [degrees(axis) for axis in axis_conversion("-Y", "Z", "Z", "Y").to_euler()]
[-90.00000250447816, -0.0, 0.0]
For example sake: Lets apply this axis conversion to all objects in the scene
import bpy
from bpy_extras.io_utils import axis_conversion
context = bpy.context
m = axis_conversion(from_forward='-Y',
from_up='Z',
to_forward='Z',
to_up='Y').to_4x4()
scene = context.scene
for o in scene.objects:
o.matrix_world = m * o.matrix_world
Image below shows the result. Globally all objects are transformed to our new global scheme of Y up and Z forward. Locally though, Suzanne is still Z up -Y forward.
To locally transform Suzanne to our new system rotate her vertex coordinates by the rotation, then rotate the object coordinates back accordingly. In this answer I prattled on about local and global coordinates. What we are doing here ultimately is applying the axis conversion rotation to Suzanne.
To apply rotation I've rotated the vertex coordinates by the axis transform rotation. (In bmesh
could use bmesh.ops.rotate(bm, geom=bm.verts[:], matrix = rot)
)
import bpy
from bpy_extras.io_utils import axis_conversion
context = bpy.context
m = axis_conversion(from_forward='-Y',
from_up='Z',
to_forward='Z',
to_up='Y').to_4x4()
rot = m.to_quaternion().to_matrix()
irot = rot.to_4x4().inverted()
scene = context.scene
for o in scene.objects:
o.matrix_world = m * o.matrix_world
if o.type == 'MESH':
# apply to mesh
o.data.transform(rot)
'''
for v in o.data.vertices:
v.co = rot * v.co
'''
# rotate globally inverse.
o.matrix_world *= irot
Image below shows the result, now our axis conversion has been applied to both the objects globally, and mesh objects locally.