2007/2/9

空を自由に飛びたいな  VRMスクリプト禅問答
ハイ!
VRMスクリプトぉ〜

  あん   あん   あん
闇・闇・闇

バグってて〜も大好き、だ〜もん〜♪

*     *     *

先だって「時刻tに対してx,y,z座標を導出する関数さえ定義できれば、どんな動線を描くフライスルーカメラだってスクリプトで記述出来る」と書いたが、これを自分でやりたい人への援護射撃。居るのか、そんな暇なヤツ。

[レイアウトスクリプト]
//カメラ位置変数
Var CameraX
Var CameraY
Var CameraZ
//視線位置変数
Var ViewX
Var ViewY
Var ViewZ
//イベント管理変数
Var TimerEvent
//遷移変数
Var T
Var IncrementT
setf T {初期値}
setf IncrementT {増分}
//イベント設定
SetEventTimer this MtdFlyCamera TimerEvent 33

//フライスルーカメラ制御メソッド
BeginFunc MtdFlyCamera
//ベクトル変数
Var CameraPosition
Var ViewPosition
GetFlyCameraPos CameraPosition ViewPosition
//カメラ・視線位置算出
call this MtdCalcCameraXYZ
call this MtdCalcViewXYZ
//ベクトル変数設定
SetVectorX CameraPosition CameraX
SetVectorY CameraPosition CameraY
SetVectorZ CameraPosition CameraZ
SetVectorX ViewPosition ViewX
SetVectorY ViewPosition ViewY
SetVectorZ ViewPosition ViewZ
//カメラ位置更新
SetFlyCameraPos CameraPosition ViewPosition
//遷移変数更新
add T IncrementT
EndFunc

//カメラ位置算出メソッド
BeginFunc MtdCalcCameraXYZ
//一時変数
Var TmpX
Var TmpY
Var TmpZ
Var TmpT
//変数Tを壊さないようにローカル変数に退避
mov TmpT T
//
//ここでTmpTからTmpX,TmpY,TmpZを算出する
//

//算出結果のグローバル変数への書き出し
mov CameraX TmpX
mov CameraY TmpY
mov CameraZ TmpZ
EndFunc

//視線位置算出メソッド
BeginFunc MtdCalcViewXYZ
//一時変数
Var TmpX
Var TmpY
Var TmpZ
Var TmpT
//変数Tを壊さないようにローカル変数に退避
mov TmpT T
//
//ここでTmpTからTmpX,TmpY,TmpZを算出する
//

//算出結果のグローバル変数への書き出し
mov ViewX TmpX
mov ViewY TmpY
mov ViewZ TmpZ
EndFunc
上掲スクリプトをレイアウトスクリプトとして組み込み、太字部分を変数tから、カメラ/視線位置のx,y,z座標を算出するロジックに書き換えれば、自動的にレイアウトの中を飛んでいくフライスルーカメラを実現することが出来る。

たとえば、先にリリースした“水平楕円軌道フライスルーカメラ”スクロールでは、太字部分がそれぞれ、

カメラ位置
  x = cos(t) × 500
  y = 100
  z = sin(t) × 500
視線位置
  ビュワー起動時のフライスルーカメラ視線位置
  = ビュワー起動時のアクティブ編成の先頭車位置

※簡易Wizardで組み込んだ場合

になっている。実際には楕円離心率や、楕円のx-z軸に対する傾きを考えているので、もう少しやっていることはややこしいが、基本はこれ。実際にスクリプトでどう書くか、については件のスクロールを各自で読んでいただきたい(ただし、このスクロールの構造は、視線座標が固定されている関係で上掲サンプルスクリプトとは異なる)。

円軌道を描くべく三角関数を使ったので、やたら敷居が高く見えるかも知れないが、これは必須ではない。シンプルな例としては、以下のようなのもアリだ。

カメラ位置
  x = t
  y = t
  z = t

t=0.0、33ミリ秒毎の増分を1.0とすると、カメラ位置はレイアウトの左上端の地面から始まり、秒速30mmでレイアウト右下方向へ向かい、斜め上45度の角度で上昇していくことになる。太字部分に入れ込むスクリプトに直せば、
mov TmpX TmpT
mov TmpY TmpT
mov TmpZ TmpT
になる。まぁ、一次式の範疇でやる限り、軌道は直線にしかならないので、せめて遷移変数tの二次式くらいにはしたいところだが、そこはお好みだ。ちなみに、二次式にするのであれば、tを十分に小さな値で遷移させるか、あるいは大きな定数で割るかしないと、あっという間に座標系がレイアウトサイズからはみ出すので要注意。

視線位置については、大雑把に考えて4つの方法がある。

(1)拙作スクロールのように固定してしまう方法。ある一点を見つめたまま、カメラ位置だけが変化していく動きになる。
(2)カメラ位置とは別の関数で導く。複雑な動きが実現できるが、実用的なものを作るのは多分難しい。
(3)カメラ位置に三角関数で導かれる一定の長さのベクトルを加算する方法。視線の向きを意図的にコントロールしたい場合はコレ。
(4)カメラ位置を導く関数に t + α の値を代入する方法。要するに、カメラの未来または過去の位置になるので、視線は進行方向かその逆を向き続ける。

以上が基本的な考え方で、アイデア次第で何でも作れる。我こそはと思う人は挑戦して欲しい。で、うまくいったらスクリプトを公開してくれ、パクるから。

本稿では、代数関数的な方法について書いた。4.0.5.4で追加されたベクトル関連の命令を使えば、より直感的なベクトル幾何学的な方法でカメラ軌道/視線向きの制御が出来るはずだが、ボク自身がまだそこまで評価しきれていない。何か面白いことが出来そうだとわかったらまた書く。もし書かなかったら、元来数学が苦手なボクちゃんの脳味噌がパンクしたってことなので、そっとしておいてね。
0

コメントを書く

この記事にはコメントを投稿できません




teacup.ブログ “AutoPage”
AutoPage最新お知らせ