わりと試行錯誤してしまったので、自分へのメモも兼ねて投稿します。
MaxScriptで、オブジェクトの回転行列だけ取り出したいという事がありました。
しかし、オブジェクトが持っているプロパティは、各成分は、値として所持しており、『拡大』『回転』『平行移動』が合成されたトランスフォームだけだったりします。→ 参考
その為、各成分だけの行列を取り出したい場合は、以下の2通りになると考えられます。
- オブジェクトの所持ているプロパティから作成する
- 合成トランスフォームから、抜き出す
1の方法は上手く行かなかった為、2の方法で取り出しました。
検証環境
3DS Max 2022 ※ ツールのアップデートが遅れている為、2022で検証しています
作成したソースコード
関数化して、すぐに使えるようなコードになっています。
引き数は、取り出したいオブジェクトのtransformプロパティとなっています。
『拡大行列』『平行移動行列』に関しては、単位行列に必要な成分を入れて、なるべくプレーンな状態の行列を作成しています。
『回転行列』は、拡大成分が合成されている為、一度、拡大行列を作成し、その逆行列を使って抜き出しています。
行列の計算に関しては、 こちらの記事を参考にさせていただきました。
-- execute使用時は、グローバルでないと駄目
oPyramid001 = execute( "$Pyramid001" )
oPyramid002 = execute( "$Pyramid002" )
-- Pyramid002の位置をリセット
oPyramid002.transform = matrix3 1
-- 平行移動行列を抜き出す
fn GetLocationMatrix _mtx =
(
-- 行成分抜き出し
local pRow1 = [1, 0, 0]
local pRow2 = [0, 1, 0]
local pRow3 = [0, 0, 1]
local pRow4 = _mtx.row4
-- 平行移動行列作成
local outputMtx = matrix3 pRow1 pRow2 pRow3 pRow4
outputMtx
)
-- 拡大行列を抜き出す
fn GetScaleMatrix _mtx =
(
-- 行成分抜き出し
local inRow1 = _mtx.row1
local inRow2 = _mtx.row2
local inRow3 = _mtx.row3
-- 拡大・縮小行列作成
local mtxX = sqrt ( inRow1.x * inRow1.x + inRow2.x * inRow2.x + inRow3.x * inRow3.x )
local mtxY = sqrt ( inRow1.y * inRow1.y + inRow2.y * inRow2.y + inRow3.y * inRow3.y )
local mtxZ = sqrt ( inRow1.z * inRow1.z + inRow2.z * inRow2.z + inRow3.z * inRow3.z )
local sRow1 = [mtxX, 0, 0]
local sRow2 = [0, mtxY, 0]
local sRow3 = [0, 0, mtxY]
local sRow4 = [0, 0, 0]
local outputMtx = matrix3 sRow1 sRow2 sRow3 sRow4
outputMtx
)
-- 回転行列を抜き出す
fn GetRotationMatrix _mtx =
(
local scaleMtx = GetScaleMatrix _mtx
local ideScaleMtx = inverse scaleMtx
-- 行成分抜き出し
local inRow1 = _mtx.row1
local inRow2 = _mtx.row2
local inRow3 = _mtx.row3
local inRow4 = scaleMtx.row4
-- 回転・拡大行列抜き出し・作成
local srMtx = matrix3 inRow1 inRow2 inRow3 inRow4
-- 逆行列で行列を求める
local outputMtx = srMtx * ideScaleMtx
outputMtx
)
--
-- 動作テスト
--
(
-- 拡大行列を取得
local scaleMtx = GetScaleMatrix oPyramid001.transform
-- 回転行列を取得
local rotationMtx = GetRotationMatrix oPyramid001.transform
-- 平行移動行列を取得
local locationMtx = GetLocationMatrix oPyramid001.transform
-- 拡大 x 回転 x 平行移動
local gousei = scaleMtx * rotationMtx * locationMtx
-- 別のオブジェクトに反映させて行列のチェック
oPyramid002.transform = gousei --結果を反映
print scaleMtx
print rotationMtx
print locationMtx
print gousei
)
結果
実行結果です。
Pyramid001が表示されている状態です。
Pyramid001は、拡大・回転・平行移動されているオブジェクトです。
Pyramid002が表示されている状態です。
Pyramid002は、初期状態で何の変換も加えていないオブジェクトです。
スクリプトでPyramid001と同じ変換を与えています。
二つのオブジェクトを表示した結果です。
重なっている事が確認できると思います。
おまけ
もう一つの面白いアプローチとしては、拡大・回転・平行移動のプロパティから、行列を作るという方法があった為、試しましたが、こちらは、私の方では上手く行きませんでした。
合成した行列をPyramid002に反映したところ、若干ずれがありました。
これは、Maxのバージョンによる挙動の変更などの違いかも知れませんが、各プロパティから行列を作れる事がわかり勉強になりました。