【Blender】カメラフォーカスの座標を取得する Python
【告知!】
— と り🐔 (@t0rry_) 2021年9月17日
Camera_Listアドオン V0.9.2を公開しました!
オブジェクトモード以外からでもカメラからのビューができるようになりました!
折角なので動画も作ってみました(爆音注意)
リリースページはこちら↓https://t.co/gHqD366Hk9#b3d pic.twitter.com/kfiDotGZEL
とりあえずカメラのフォーカス座標の取得ができたのでメモ
カメラのフォーカス座標取得までのフロー
詳細
1.情報の取得方法
位置
bpy.context.active_object.location
回転
bpy.context.active_object.rotation_euler
※取得する値はクォータニオンではなくオイラー角
※UI上表示されているのは度数法だが、BlenderAPI上で取得できるのは弧度法なので注意
カメラからの距離
bpy.context.active_object.data.dof.focus_distance
(実際に公開したアドオンの場合はリストに登録したデータからオブジェクトを参照している)
細かい話になるが、位置や回転については後ほど各要素(x、y、z)を分解して処理を行うので
取得する段階で別々の変数に値を代入した。
位置(x軸の値を取得するとき)
bpy.context.active_object.location.x
回転(x軸の値を取得するとき)
bpy.context.active_object.rotation_euler.x
2.極座標変換について
moromi-senpy.hatenablog.com
Pythonで極座標変換を行うにあたって先の記事に非常に助けられました。
仰角の取得(φ)

X軸方向の回転が仰角の元データになる。
bpy.context.active_object.rotation_euler.x
ここで注意したいのが、X軸の回転がそのまま仰角にならないこと
X軸回転が0の場合の極座標Θは180度(π)になります。

よって、単純にX軸回転の値を扱うのではなく仰角向けに計算を挟む必要があります。
方位角(Θ)

Z軸方向の回転が方位角の元データになる。
bpy.context.active_object.rotation_euler.z
仰角と同様に方位角についてもそのまま値を利用してΘにならない
Z軸回転が0の場合の極座標φは90度(2/1π)になります。
こちらも方位角向けの計算が必要です。
極座標変換
取得したΘ、φ、rをもとに極座標変換をする
x = r sinΘ cosφ
y = r sinφ sinφ
z = r cosΘ
この計算を行うにあたってNumpyという数値演算ライブラリを使いました。
import numpy as np
numpyをimportするのを忘れずに
newPosition = np.empty([1,3], dtype=np.float64)
newPosition[:,0] = bpy.context.active_object.data.dof.focus_distance * np.sin(theta) * np.cos(phi)
newPosition[:,1] = bpy.context.active_object.data.dof.focus_distance * np.sin(theta) * np.sin(phi)
newPosition[:,2] = bpy.context.active_object.data.dof.focus_distance * np.cos(theta)先ほど冒頭に載せたサイトのコードを参考にさせていただいています。
実際にアドオンで使用したコード
class CML_OT_ViewCoordinate(bpy.types.Operator):
"""Calculation to View Coordinate """
bl_idname = "camera_list.view_coordinate"
bl_label = "view coordinate"
@classmethod
def poll(cls, context):
return context.scene.camera_list
def execute(self,context):
#00 camera_list,index
index = context.scene.list_index
camera_list =context.scene.camera_list[index]
#01 get camera's locations(x,y,z)
original_location = camera_list.ob.location
#02 get camera's rotations
#02-1 (euler)
original_angle_x = camera_list.ob.rotation_euler.x
original_angle_z = camera_list.ob.rotation_euler.z
#03 calculate theta (180° = π = np.pi )
if original_angle_x < np.pi:
theta = np.pi - original_angle_x
else:
theta = 3 * np.pi -original_angle_x
print("B :x< 2pi , x > pi")
#04 calculate phi
if original_angle_z < np.pi:
phi = original_angle_z + (np.pi / 2 )
else:
phi = original_angle_z + (np.pi / 2 )
print("B :z > 2pi , z > pi")
#05 get camera's focus distance
original_view_distance = camera_list.ob.data.dof.focus_distance
newPosition = np.empty([1,3], dtype=np.float64)
newPosition[:,0] = original_view_distance * np.sin(theta) * np.cos(phi)
newPosition[:,1] = original_view_distance * np.sin(theta) * np.sin(phi)
newPosition[:,2] = original_view_distance * np.cos(theta)
x = newPosition[:,0]
y = newPosition[:,1]
z = newPosition[:,2]
return{'FINISHED'}※camera_listについてはカスタムプロパティでカメラの情報が代入されている
※プログラミング初心者が故に誤りがあると思いますが、参考になればと思います。

