日々適当

hibitekitou

とりあえず親の座標系にする

cg |2020-12-25

こんな感じで三つのオブジェクトObjA, ObjB, ObjCが同じ階層にいます。そいで、これらをParentコマンドでBの子供にCをAの子供にBを設定します。設定した結果が下。

この時注目したいのは位置情報が階層構造を作る前と変化ないこと。だからワールドの座標系で表示されているかと思いきや、一番親のObjAを動かしてもObjB、ObjCの情報に変化は生じません。ここの数値は何もしないと親子関係を作った時のワールド座標って事みたいです。なので(個人的には)これは全く役に立たない情報に思えます。だからObjB、ObjCのRelationsの中のParent TypeをObjectにしてやると親の座標系の数値に変わるのでそう設定したいのですけど、それに変更した瞬間、ObjBとObjCの位置は、親子関係を作った時のワールド座標の数値をローカル座標系の数値として取り扱いやがります。つまり、位置が吹っ飛ぶ。

これを回避するためのスクリプトを考えるわけですが、スケールが絡まなければ大変にシンプルで、子供を選択して以下のスクリプトを実行するだけで良いようです。

import bpy
childObj = bpy.context.selected_objects[0]
matrixWorld = childObj.matrix_world
childObj.parent_type = "OBJECT"
childObj.matrix_world = matrixWorld

ワールド座標系内での変換を保持しておいて、Parent TypeをObjectに変更した後にその値に戻してやる、って考え方。関連するオブジェクトのスケールが1ならこれで問題なく動作するようです。こいつを簡単に呼び出せるようにしておけば、当面の用は足りるかね。

ちなみに matrix_world でワールド座標系のマトリクスを扱ってますけど、ローカル座標系のそれは matrix_local でよろしいそうです。

なを、座標変換では変換行列を乗算する事が多いわけですけど、Python 3.5以降ではそれは@演算子なのだそうで、3.7.7が動いているらしいBlender 2.91.0では当然それが使えて、 matrixWorld@matrixWorld.inversed() とかやるとワールドの原点に行ってくれたりします。変換部分を勉強すればこの辺の知識が役に立ってくるはずなのだけど、とりあえず知識がないのものでスケール問題に対処できません。困ったものです。

コメント ( 0 )|Trackback ( )
 
コメント
 
コメントはありません。
コメントを投稿する
ブログ作成者から承認されるまでコメントは反映されません
 
名前
タイトル
URL
コメント
コメント利用規約に同意の上コメント投稿を行ってください。

数字4桁を入力し、投稿ボタンを押してください。