I would like to create cameras looking at origin uniformly distributed in a sphere. I got most of it right...but the cameras are looking away from the origin. I know I can get it right by a certain combination of rotations, but I want to be sure that what I am doing is 100% correct. Can someone familiar with this help me point out what's the right way to do it?
By changing the lookat slightly in the "wrong" way I can get what is expected result. However, what I would like to do is apply the coordinate transform matrix to the camera matrix after the "right" lookat is computed(right lookat==x-right,y-down,z-forward,i.e. the cv convention).
There is an additional problem with the code that looks right. The camera scale is negated for some reason. I thought scale is not affected by transform matrix. Having negative scale causes some other problem when I am converting the camera back to cv work.
looks wrong but should be correct?
looks right but wrong.
code to create cameras
import bpy import bmesh import random import math import numpy as np from mathutils import Matrix def sphere_golden_spiral(num_pts=1000): from numpy import pi, cos, sin, arccos, arange indices = arange(0, num_pts, dtype=float) + 0.5 phi = arccos(1 - 2*indices/num_pts) theta = pi * (1 + 5**0.5) * indices x, y, z = cos(theta) * sin(phi), sin(theta) * sin(phi), cos(phi) points = np.stack((x,y,z),axis=-1) return points def norm(v): return v/np.linalg.norm(v) def lookat(eye,at=np.array([0.,0,0]),up=np.array([0.,1,0])): z = norm(eye-at) x = norm(np.cross(z,up)) y = np.cross(x,z) z = -z view_mat = np.zeros((4, 4)) t =np.array([0.,0,0]) t = -np.dot(x,eye) t = -np.dot(y,eye) t = -np.dot(z,eye) view_mat[0,:3]=x view_mat[1,:3]=y view_mat[2,:3]=z view_mat[:3,3]=t view_mat[3,3]=1 return np.linalg.inv(view_mat) def rotx(a): from math import cos,sin return np.array([[1,0,0,0], [0,cos(a),-sin(a),0], [0,sin(a),cos(a),0], [0,0,0,1]]) def roty(a): from math import cos,sin return np.array([[cos(a),0,sin(a),0], [0,1,0,0], [-sin(a),0,cos(a),0], [0,0,0,1]]) def rotz(a): from math import cos,sin return np.array([[cos(a),-sin(a),0], [sin(a),cos(a),0,0], [0,0,1,0], [0,0,0,1]]) def cams_sphere(points): points = np.array(sphere_golden_spiral(points)) group = bpy.data.groups.new('Trg_sphere') context = bpy.context for i in range(len(points)): p = points[i] bpy.ops.object.camera_add() cam = context.object cam.name='Traj_sphere_%i'%i transform = lookat(p*10) #print(rotx(math.radians(-90))) #transform = np.matmul(transform,roty(math.radians(-180))) cam.matrix_world = Matrix(transform) group.objects.link(cam) cams_sphere(100)