# Rotate an object to camera view

I try to make this as clear as possible:

Starting Point

I place an object at the center (0,0,0) of the scene. Then I place a camera given a fix radius on a hemisphere around the object (and use Constraints to make it always look at the object) and render the image. I export the object as .stl with y-up and minus-z-forward, in order to open it with another library that uses this different convention.

Problem

I would like to rotate the object in such a way that it would correspond to the view of the rendered image.

Approach

The angles for azimuth and elevation are known. So I calculate the rotation matrix given the two angles (I need a homogeneous rotation matrix, thus appending the 0s and 1).

def angles_to_matrix(phi, theta):
# phi describes the azimuth
azi = phi
# theta describes the inclination angle, thus:
ele = radians(90) - theta
rol = 0

e1 = cos(rol) * cos(azi) - sin(rol) * cos(ele) * sin(azi)
e2 = sin(rol) * cos(azi) + cos(rol) * cos(ele) * sin(azi)
e3 = sin(ele) * sin(azi)
e4 = -cos(rol) * sin(azi) - sin(rol) * cos(ele) * cos(azi)
e5 = -sin(rol) * sin(azi) + cos(rol) * cos(ele) * cos(azi)
e6 = sin(ele) * cos(azi)
e7 = sin(rol) * sin(ele)
e8 = -cos(rol) * sin(ele)
e9 = cos(ele)

return np.array(((e1, e2, e3, 0), (e4, e5, e6, 0), (e7, e8, e9,0 ), (0, 0, 0, 1)))


The rotation does not look right. & I feel there could be several things going wrong:

• Did I miss something concerning the change of axis orientation?
• Is it even possible to use the same angles for calculating the sphere coordinates to calculate the rotation of the object?

Do you have any ideas?

• To clarify you wish to align forward axis of target to camera view axis? Aug 20, 2020 at 16:05
• @batFINGER I guess this is another way to put it. I always thought of the problem in terms of rotating the object accordingly. Aug 21, 2020 at 8:36

## 2 Answers

Align object to camera

This will give same result as adding an object in camera view, and using ALIGN to VIEW

By default a blender object faces -Y and has Z up. The camera on the other hand looks down -Z with Y up.

Can decompose an objects matrix into its location, rotation and scale, and then recompose.

In this case get the rotation part of the camera matrix world, transformed to -Y forward and Z up then recomposed into the object with its original scale and translation.

import bpy
from mathutils import Vector, Matrix
from bpy import context
from bpy_extras.io_utils import axis_conversion

scene = context.scene
cam_ob = scene.camera
ob = context.object

A = axis_conversion(
from_forward='Z',
from_up='-Y',
to_forward='Y',
to_up='Z').to_4x4()

loc, rot, scale = cam_ob.matrix_world.decompose()

ob.matrix_world = (
Matrix.Translation(ob.matrix_world.to_translation()) @
(rot.to_matrix().to_4x4() @ A) @
Matrix.Diagonal(ob.matrix_world.to_scale()).to_4x4()
)

• I get your point in decomposing and recomposing the matrix. Unfortunately, if I use the recomposed matrix the object is not rotated correctly. Aug 28, 2020 at 12:46
• Similarly Have never been clear on exactly what you are trying to do. Code above aligns object to look normal towards camera plane and have same up as camera. Accepted answer is rotating each point of a point cloud. "finding the rotation by trial and error" which basically appears to be the axis conversion matrix. Aug 28, 2020 at 13:07
• Nope on further investigation you are producing Matrix.Diagonal((-1, 1, 1, 1)) by way of your example. Aug 28, 2020 at 13:39

For anyone else getting lost in rotation matrices and axis orientations:

Ignore the def angles_to_matrix() function above. The calculation of the whole rotation matrix depends on the order in which you want to apply the single rotations. Also one has to consider the axis orientations.

## Solution: Let's do it step-by-step and use a bit of trial & error

We are dealing with two angles to calculate the spherical coordinates for the camera:

• azimuth: in Blender that's the rotation around z; in Blender it's defined between [-180°, 180°] (showing the front of the object)
• elevation: in Blender that's the rotation around y; since we want only the upper hemisphere it's defined between (0°, 90°] (? for some reason it behaves weird with 0°, where it will always show the object from straight above ignoring the azimuth orientation)

Now because we will do the rotation in a differently oriented system (y-up, minus-z-forward), the azimuth angle becomes a rotation around y and the elevation a rotation around x.

We use the following single rotation matrices. Careful, these ones already describe the calculation for the new system.

Last but not least: my target framework seems to use a different reference axis (?). Thus, an azimuth of -180° (front) in Blender, does not correspond to the same view in the different system. By trial and error we can find the values to correct the angles.

blender_azi = radians(0) # back of the object
blender_ele = radians(90) # zero-level view

# find out the value by trial and error
azi = blender_azi - radians(180)
ele = radians(90) - blender_ele

rotation_azimuth = np.identity(4)
rotation_azimuth[::2, ::2] = np.asarray([cos(azi), sin(azi), -sin(azi), cos(azi)]).reshape(2,2)

rotation_elevation = np.identity(4)
rotation_azimuth[1:3, 1:3] = np.asarray([cos(ele), -sin(ele), sin(ele), cos(ele)]).reshape(2,2)

rotation_matrix = rotation_elevation @ rotation_azimuth


I used the rotation matrix to rotate each point of the point cloud.

• Totally unclear what the result is here. The rotation_matrix produced above results in mirror x, ie its 4x4 identity with element (0, 0) = -1. Aug 28, 2020 at 13:37