ソラマメブログ

2007年05月07日

カメラ制御(スクリプト初級第二十二回)

最後に衝突について説明して初級スクリプト講座を終えようと思っていたのですが、最近、カメラのコントロールが意外に面白い効果を出せることに気づいたので、今回はカメラの制御について書きたいと思います。
SLで言うところのカメラとは、「視点」のことです。

通常、SLの視点はユーザーが自由に動かすことができます。
ALTを押しながらアバターを左クリックすると、そのアバターに注目したりもできますね。
結構自由なカメラコントロールが許されていて、私のように趣味でムービーを作る者にとっては重宝しています。

スクリプトからカメラをコントロールする方法も用意されており、これがまたムービー作成には非常に便利です。
どういうことかと言うと、撮影用の椅子を用意しておき、そこに座ると必ず特定の位置に視点が定まるようにできるのです。
例えば建物の建設の様子などを定期的に定点撮影したい、などという場合にも使えます。
カメラコントロール

カメラのコントロールは凝りだすと結構細かいところまで制御可能なのですが、今回扱うのはごく簡単なものだけにしておきます。
作成するものは「座ると特定の位置に視点が固定される椅子」です。

私はこれを使って映画館の椅子を作りました。
座ると視点が勝手にムービーのスクリーンに固定されるものです。
応用としては、座ると遠景が見える望遠鏡とか、乗り物に乗ったときに運転席からの視点にするなどが考えられます。

使う関数は二つです。
一つは、カメラの位置を決める関数llSetCameraEyeOffsetです。
もう一つは、カメラの向き(どこを見るか)を決める関数llSetCameraAtOffsetです。

これらの関数は「アバターがオブジェクトに座ったとき」の視点をコントロールします。
llSitTarget関数と同様、あらかじめ設定しておかなければ動作しません。
現在座っているアバターの視点を変えられるわけではありませんので注意して下さい。

それぞれの関数について見てみましょう。

  llSetCameraEyeOffset(vector offset);

この関数はアバターがオブジェクトに座ったときのカメラの位置を設定します。
引数offsetはオブジェクトからの相対位置です。
例えば、offsetに<0.5, 0.0, 1.0>という値を設定すると、カメラはオブジェクトからX方向に0.5m、Z方向に1m移動した場所にセットされます。

  llSetCameraAtOffset(vector offset);

こちらの関数はアバターがオブジェクトに座ったときのカメラの向きを設定します。
引数offsetはカメラが向く方向(相対位置)です。
例えば<0.0, 0.0, 2.0>という値を設定すると、カメラはオブジェクトのZ方向2mの位置を向きます。

少々わかりにくいので図にしてみました。

カメラ制御(スクリプト初級第二十二回)

この図では、カメラはオブジェクトからX方向2m・Z方向4.5mの位置から、Xマイナスの方向を見ることになります。
クライアントの視界となる位置に、見せたいものを配置しておけば、このオブジェクトに座った人は皆同じ景色を見ることができます。

定点カメラスクリプト

カメラの位置が相対指定というのは少々わかりにくいので、絶対座標で指定できるようなスクリプトを組んでみます。
ただし、回転を考慮しませんので、座るためのオブジェクトの回転はゼロである必要があります。

vector sit_pos = <0.0, 0.0, 0.5>;
vector sit_rot = <0.0, 0.0, 0.0>;
vector c_pos = <102.0, 70.0 ,24.5>;
vector c_vec = <97.5, 70.0 ,24.5>;

set_view(){
  vector object_pos=llGetPos();
  llSetCameraEyeOffset(c_pos - object_pos);
  llSetCameraAtOffset(c_vec - object_pos);
}

default {
  state_entry(){
    llSitTarget(sit_pos, llEuler2Rot(sit_rot * DEG_TO_RAD));
    set_view();
  }
  
  moving_end(){
    set_view();
  }
}

変数sit_posとsit_rotはオブジェクトに座る位置を指定するための値です。
state_entryの中でllSitTarget関数に使っているだけです。

c_posはカメラの位置を指定します。
相対座標ではなく絶対座標です。
同じく、c_vecはカメラの見る点(視線の方向)を絶対座標で指定するものです。

ユーザー関数set_view()の中で、c_posとc_vecの値を使ってカメラ位置を設定しています。
まずllGetPos()関数でオブジェクトの位置を取得し、c_pos及びc_vecから減算することで、相対座標に変換します。
こうして求めた相対座標をllSetCameraEyeOffset関数とllSetCameraAtOffset関数に渡しています。

このようにすると、オブジェクトの位置がどうであろうと、特定の位置に視点が固定されます。
とは言っても、llSetCameraEyeOffset関数やllSetCameraAtOffset関数で指定できる値には限界値があると思いますので(未確認です。多分10メートル程度ならば問題ないでしょう)遠く離れた場所までは見れないかもしれませんが(^^;

一つだけ見慣れないイベントがありますね。

  moving_end(){
     // 移動し終わったときの処理
  }

moving_endイベントはオブジェクトが「移動し終わったとき」に発生するイベントです。
ここではオブジェクトが移動したときに、カメラの相対位置を設定し直す為に使っています。

なお、「移動し始めたとき」のイベントは、

  moving_start(){
     // 移動し始めたときの処理
  }

ご想像通りかと思います。
試したことはないですが、乗り物などで「走り始めたとき」に音を鳴らしたいとかいう場合に使えるのではないでしょうか。

今回のポイント

・座ったときのカメラ位置の設定:
  llSetCameraEyeOffset(vector offset);

・座ったときのカメラの向く方向の設定:
  llSetCameraAtOffset(vector offset);

・移動系イベント:
  moving_start(){
     // 移動し始めたときの処理
  }

  moving_end(){
     // 移動し終わったときの処理
  }

短めですが、今回はこれにて。



同じカテゴリー(初級スクリプト)の記事画像
衝突判定(スクリプト初級第二十三回)
センサーを使おう(スクリプト初級第二十回)
HUDを作ろう(スクリプト初級第十六回)
prim間通信(スクリプト初級第十五回)
アニメさせよう(スクリプト初級第十三回)
お金を扱う(初級スクリプト第十一回)
同じカテゴリー(初級スクリプト)の記事
 衝突判定(スクリプト初級第二十三回) (2007-05-08 12:15)
 デモ商品を作ろう(スクリプト初級第二十一回) (2007-05-02 12:15)
 センサーを使おう(スクリプト初級第二十回) (2007-05-01 12:15)
 ステートのこと(スクリプト初級第十九回) (2007-04-27 12:15)
 rez!(スクリプト初級第十八回) (2007-04-26 12:15)
 音を鳴らそう(スクリプト初級第十七回) (2007-04-25 13:35)
この記事へのトラックバック
カメラ制御 http://miz.slmame.com/e4546.html
diary/2007-05-08【Help Secondlife (PukiWiki/TrackBack 0.4)】at 2007年05月08日 10:36
セカンドライフ(secind life)でのカメラコントロールとマウスルックモード についてセカンドライフ(second life)では画面を写真で取ったり、視野をかえたりすることが基本操作の一つです。...
セカンドライフのカメラコントロールとマウスルックモード基本操作攻略【セカンドライフ仮想空間の人生ゲーム徹底攻略 】at 2007年06月30日 21:47
この記事へのコメント
いつも愛読しています!カメラ制御について質問。
このスクリプトだとアバターが自分でカメラコントロールしているときは視界が変わらないような気がするんですが。
普通に歩いて椅子に座ったときはいいんだけど、飛んでいて上空から椅子をズームアップ&座っても視界が変わらないんです・・・・
どんな状態でも視界を変えるにはアバターのカメラコントロールを制御する必要があるんでしょうか?
そのためには、PERMISSION_TRACK_CAMERAなどを使ってパーミッションを取得ってパターンになるのでしょうか?

またパーミッションのダイアログ表示をなくすにはルートプリムにスクリプトを入れればいいと聞きましたが、うまく行きません(涙)。
Posted by chika Noel at 2007年06月11日 11:43
>chika Noelさん

こんにちは。
ALTズームなどをしている最中にカメラのコントロールが効かないのはSLの仕様だったりします(^^;
ただし、座ったあとにESCキーなどでALTズームを抜けると、カメラコントロールが有効になります。

この記事で紹介しているカメラコントロールは、座った状態の視点しか扱えませんが、llSetCameraParams関数(パーミッションが必要になります)を使った場合は、立っているアバターの視点をコントロールすることができるようになります。
ですが、どちらの方法を使ったとしても、ALTズーム等を無効にすることはできません。

といった仕様からすると、あとはもう「ESCを押してカメラ制御をデフォルトに戻してください」というメッセージを出すくらいしか対応策がないですが・・・(^^;

なお、「パーミッションのダイアログ表示をなくすにはルートプリムにスクリプトを入れればよい」というのはあくまでもアタッチメントにスクリプトを組み込んだ場合の話になります。
ワールド内に配置されているオブジェクトに関しては、必要に応じて必ずパーミッションダイアログが表示されます。
これまたSLの仕様です(^^;
Posted by Miz at 2007年06月11日 15:51
なーるほど。座ってからでもESCキーで抜けられるんですね。知らなかった。じゃ、そのようにメッセージを出すようにしてみます。
いつもためになる記事をありがとうございます。
現在SIMを造成中ですが、シカケ作りのためにこの解説記事はほんとに役に立ちます。もう何回見たかわからないくらいです。
リファレンスも期待してまーす。
Posted by chika Noel at 2007年06月12日 18:26
>chika Noelさん

カメラコントロールはもともと動画作るときのためにいじってたんですが、応用するといろいろな仕掛けが作れますよね。
「見せたいものを見せたい視点で見せられる」のが良いところです。

リファレンス・・・(滝汗
Posted by Miz at 2007年06月14日 14:06
 
<ご注意>
書き込まれた内容は公開され、ブログの持ち主だけが削除できます。