【怎麼生】
VRMoviesの動画54作目でカメラがズームアップしていましたが、あれはどうやれば出来るんですか。
【説破】 4.0.1.2
FOV(Field of View)を制御することで実現できます。
スクリプトのコーディングに入る前にFOVについてサラッとご説明しておきましょう。まずは下の模式図をご覧ください。

<FOVの図>
FOVは日本語でいう「視野角」に当たります。
上図では、地上カメラから3種類のFOVが右に向かっています。赤がFOV120°、緑がFOV90°、青がFOV30°であり、緑色で示しているのが特に設定を変えなかった場合のデフォルト値になります。FOV90°というのは、カメラを中心に上下左右45°ずつ(それぞれ両方向に広がって計90°)が視界に入る、という意味です。FOVが120°と大きくなると視界に入る範囲が広がり、逆に30°と小さくなると狭くなります。
一方で、視界の広い狭いに関わらず、VRMビュワーの画面の大きさは変わりませんから、FOVが大きくなれば相対的に視界の中の「何か」は小さくなり、逆にFOVが小さくなれば「何か」は大きく見えることになります。前者がズームアウトを、後者がズームインを意味することはご理解いただけますね?
なお、FOVの設定のみであればスクリプトを書く必要はありません。地上カメラについてはカメラ設定ダイアログで、編成カメラについては環境設定ダイアログで変更可能です(後者は4.0.1.2の時点ではスクリプトで制御できません)。ただ、これでは、特に地上カメラについては単に「何か」に対するカメラ位置を変えたのとあまり変わりません(注)ので、スクリプトを使ってFOVを動的に変化することで特殊な効果を狙うわけです。
注:厳密には意味が若干異なります、FOVを小さくすると望遠レンズで覗いたような効果が、大きくすると魚眼レンズで覗いたような効果が得られます。
では、拙第54作動画に組み込んだ地上カメラスクリプトをご覧にいれましょう。これは「カメラが列車を検知したら、FOV20°から120°へとズームアウトする」という動作をするものです。
//グローバル変数宣言
Var VarFOVStart
Var VarFOVEnd
Var VarFOVDelta
Var VarFOVNow
Var EventID
Var ZoomID
//FOV初期値→終了値設定
setf VarFOVStart 20.0
setf VarFOVEnd 120.0
//FOV変位速度(角度/1フレーム)
setf VarFOVDelta 0.5
//イベント定義
SetEventCamera MtdZoomStart EventID
//
//ズーム開始メソッド
//
BeginFunc MtdZoomStart
//FOV初期値取得
mov VarFOVNow VarFOVStart
//FOV設定
SetCameraFOV VarFOVNow
//ズームメソッド開始
SetEventTimer this MtdZoomFOV ZoomID 33
EndFunc
//
//ズームメソッド
//
BeginFunc MtdZoomFOV
add VarFOVNow VarFOVDelta
//ズームインの場合は・・・
//sub VarFOVNow VarFOVDelta
SetCameraFOV VarFOVNow
if>= VarFOVNow VarFOVEnd
//ズームインの場合は・・・
//if<= VarFOVNow VarFOVEnd
KillEvent ZoomID
endif
EndFunc
基本的な考え方は、カメラのFOVを20°から0.5°ずつ加算して120°に至らせよう、というものです。
まず注意していただきたいのは、スクリプトでFOVを扱う場合「小数」を使う必要があるという点です。値の設定にはsetではなくsetfを使います。スクリプト冒頭でズームアウト開始時・終了時のFOVと1フレーム(後述)毎の加算値をそれぞれ20°、120°、0.5°にしているのがそれです。
続いて、FOV初期値をカメラに設定し、列車の検知に連動するイベントを定義しています。ここでは、カメラが列車を検知したらメソッドMtdZoomStartが実行されるようにしています。
そのMtdZoomStartですが(BeginFunc MtdZoomStart以降)、やっていることはSetEventTimer命令を使って「33ミリ秒毎にメソッドMtdZoomFOVを実行せよ」と宣言するだけのものです。このメソッドがズームアウトをおこなうのではなく、ズームアウトをおこなうメソッドMtdZoomFOVが実行されるような仕掛けをしているだけですね。
なお、ここで指定している「33ミリ秒」というのは、約1/30秒になります。ピンと来る人は来ると思いますが、これはVRMビュワーがF4キーを押しっ放しにすることで毎秒30枚のスクリーンショットを生成することと関係しています。つまり、スクリーンショットが1枚生成される=1フレームごとにズームアウト処理が実行されることを狙っています。無論、これは私が動画生成を目的にしているからなので、必ずしも33ミリ秒である必要はありません。が、滑らかなズームアウトをおこないつつビュワーに不必要な負荷をかけないという意味で妥当な値とは思います。
最後にズームアウト処理をおこなうメソッドMtdZoomFOVですが、これはまず現在のFOVに1フレーム毎の加算値を加え(add命令)、これをカメラFOV値として設定します(SetCameraFOV命令)。これだけでズームアウトは実現されます。
ただし、これだけだとズームアウトしっ放しになってしまうので、続くif>=命令で現在のFOVがズームアウト終了時のFOV値を超えたかどうかチェックし、超えた場合は33ミリ秒毎にこのメソッドが実行される設定を解除しています(KillEvent命令)。
スクリプト文中にもコメントを挿入していますが、初期値と終了値の大小関係を逆転させ、addをsubに、if>=をif<=に変更すればズームイン処理もおこなうことができます。工夫次第で面白い効果が得られるので、自作レイアウトに組み込んでいろいろ試してみてください。
なお、サンプルスクリプトではわかり易さを優先して「ズームアウトの開始」と「ズームアウト処理」を2つのメソッドに分けていますが、これを1つのメソッドでおこなう方法もあります。これは読者の皆さんの課題として残しておきましょう。

0