[TouchDesigner] スイッチングで任意のカメラ位置にヌルっと移動させる


## はじめに

こんにちは！プログラマーをしておりますアツシといいます！
TouchDesigner Advent Calendar 2019 day15の記事にしました。よろしくお願いします。

簡単に自己紹介をします！

仕事ではレジャー施設等にある体現型ゲームのシステムを作ったりしてます。
会社ではUntiyで実装することが多いんですが、個人でVJ映像やインタラクティブな作品を作る際はよくTouchDesignerを使用しています！
インスタレーション、アート×テック大好きです！！同じような方是非とも一緒に飲みましょう！

先日の[タワーアカデミーのTouchDesigner講座](http://www.billboard-japan.com/d_news/detail/81305)ではTAとして参加させていただきました。
そこで、違う学習内容においても質問としてよく上がっていた点や疑問点として上がりそうな点等を踏まえ、TD初心者の方々に向けてなるべく丁寧に解説するよう努めたいと思います。

##概要
ボタンを押すと、任意の場所に滑らかに遷移するカメラワークについて解説します。
ボタンは複数設定を可能にします。

※下記にメリット、デメリット追記しました！用途によって[CameraBlendCOMP](https://docs.derivative.ca/Camera_Blend_COMP)と使い分けるのが良いかと思います！
#####デメリット
・少々手間（CameraBlendCOMPを使用した方がお手軽）

#####メリット
・CameraCOMP以外にも応用できる（GeometryCOMPやSOP等）

・遷移パターンが豊富（例：A点→D点の直接遷移が可能、前述のCameraBlendCOMPだとA点→B点→C点→D点のように順番を追う遷移しかできない）

##サンプルファイル
[CameraTransitionSample.toe](https://drive.google.com/file/d/1BjS-iDb8dNm08XnUjZdohg4st_YWND77/view?usp=sharing)
[CameraTransitionSample.tox](https://drive.google.com/file/d/1e6rlSlWZu4nQpFNFPod3UMyly_E-ifP-/view?usp=sharing)

##TouchDesignerのカメラワークに関する記事
カメラのスイッチングに関しては、
[@atsonic](https://qiita.com/atsonic)さんの[**TouchDesigner 複数カメラをボタンでスイッチング**](https://qiita.com/atsonic/items/8aeb32c4933b9f05673b)でも詳しく紹介されていますが、今回は違う手法で紹介したいと思います！

また、カメラを扱う際の基本的な操作については、
[@narumin256](https://qiita.com/narumin256)さんの[**TouchDesigner 使いはじめた頃知りたかったことTips**](https://qiita.com/narumin256/items/25710e6952079e1b3348)のカメラワークの項目で解説されています。

##完成イメージ
今回解説する内容は、TECHS.2019 in TIMMでイントロの階段を上がっていくカメラワークで使用しています。
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">バナレモ最高。TIMM最高。<br>でした！<a href="https://twitter.com/hashtag/BananaLemon?src=hash&amp;ref_src=twsrc%5Etfw">#BananaLemon</a> <a href="https://twitter.com/hashtag/TIMM?src=hash&amp;ref_src=twsrc%5Etfw">#TIMM</a> <a href="https://twitter.com/hashtag/TECHS?src=hash&amp;ref_src=twsrc%5Etfw">#TECHS</a><a href="https://twitter.com/hashtag/%E3%83%90%E3%83%8A%E3%83%AC%E3%83%A2?src=hash&amp;ref_src=twsrc%5Etfw">#バナレモ</a> <a href="https://twitter.com/hashtag/VJ?src=hash&amp;ref_src=twsrc%5Etfw">#VJ</a> <a href="https://t.co/T9oriz3v2p">pic.twitter.com/T9oriz3v2p</a></p>&mdash; Atsushi (@atsh_mtsk0122) <a href="https://twitter.com/atsh_mtsk0122/status/1189859194649731072?ref_src=twsrc%5Etfw">October 31, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>



<blockquote class="twitter-tweet"><p lang="en" dir="ltr">Camerawork Control System in <a href="https://twitter.com/hashtag/TouchDesigner?src=hash&amp;ref_src=twsrc%5Etfw">#TouchDesigner</a> <a href="https://t.co/R6xAWg3csV">pic.twitter.com/R6xAWg3csV</a></p>&mdash; Atsushi (@atsh_mtsk0122) <a href="https://twitter.com/atsh_mtsk0122/status/1206047194257620992?ref_src=twsrc%5Etfw">December 15, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

##動作環境
TouchDesigner 099 2019.19930
Windows10


##手順１　制御するカメラを配置する
COMPからCameraCOMP、GeoCOMP、LightCOMPを配置、TOPからRenderTOP、NullTOPを配置し、繋げます。
TouchDesignerユーザーにはお馴染みの手順ですね。

次に、CameraCOMPの名前を変更します。
ここでは例として"controlled_cam"とします。このカメラは位置情報等を受け取る用として使用します。
![00_controlled_cam.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514335/cef98c71-3106-56f3-77bb-9e498013d2a5.png)
※名前を変更した際に下のようなダイアログが表示されます。"Yes To All"を選択して下さい。
![01_dialog.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514335/c726307f-c1ce-92e4-7f94-df09ac447a50.png)

##手順２　位置情報を出力するカメラを配置する
[ReplicatorCOMP](https://www.kalium.net/image/2018/04/25/td%E3%81%A7%E3%82%AA%E3%83%9A%E3%83%AC%E3%83%BC%E3%82%BF%E3%82%92%E5%8B%95%E7%9A%84%E3%81%AB%E8%A4%87%E8%A3%BD%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/)は使用せず、CameraCOMPを複数追加していきます。

ここでは例として４つ追加し、名前をcam0, cam1, cam2, cam3とします。
名前を0から始めたのは、後述するButtonのナンバーと同じにする為です。
###<font color="Orange">**「カメラの名前と、ボタンの名前の末尾の数字が同じになっていること」**</font>
<font color="****"></font>が重要です！

この複数のカメラは位置情報等を出力する為に使用します。
![cam0-4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514335/fe681baf-e173-da2d-f683-7f9b6827dce4.png)

##手順３　カメラ位置を決める
次にCameraCOMPの位置や角度を任意の値に設定します。
設定は、XformタブのTranslate、Rotate、Pivot等の欄に直接値を入力する方法と、
オペレーターをアクティブ（オペレータの一番右下のボタンを押す）に切り替えた状態で、マウス操作で値を変更する方法等があります。

下のGIFはマウス操作で値を変更しています。
慣れてしまえば、マウス操作の方が直感的に場所を決めることができるのでおススメです！
![camPos2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514335/62125a41-585c-6142-96a0-bb6c0e838aec.gif)



下記、CameraCOMPのマウスの操作メモです。

| マウス操作       | カメラ |
|:-----------------|:------------------|
|左クリックを押しながら前後移動|横軸回転|
|左クリックを押しながら左右移動|縦軸回転|
|マウスホイールを押しながら前移動|Geometryに近づく|
|マウスホイールを押しながら後ろ移動|Geometryから離れる|
|右クリックでドラッグ|平行移動|

##手順４　ボタンを配置する
値の調整が終わったら、左上にある
OpenPaletteを押し、Derivative > UI > Basic Widgetsを選択します
下の一覧からbuttonRadioをネットワークエディターの何もないスペースにドラッグ＆ドロップします
![button.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514335/5219c8fb-7a30-a4cd-87bb-0045bb23fab8.png)




buttonRadioのRadioタブの一番上にあるButton LabelsをCameraCOMPの名前末尾の数字と同じになるよう設定します。
今回はcam0、cam1、cam2、cam3に設定しているので 0 1 2 3 と設定します。
![button01.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514335/bbdcf005-a440-f1ff-bf7f-ad6718a2589c.png)


buttonRadioにNullCHOPを繋ぎます。この時NullタブにあるCookTypeをAutomaticからSelectiveに変更すると処理負荷を軽減できます。
![button02.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514335/698b80ee-f4f5-c929-0ec5-13c6738efe53.png)


##手順５　NullCHOPの値を、ConstantCHOPに入力
何もないところでConstantCHOPを配置し、chan1をtxに名前を変更します。
同様に、下の欄にty,tz,rx,ry,rzと入力します。

（※マウスカーソルで位置等の調整を行った場合は、Pivotの値も変わっているのでCameraCOMPのPivotの値も変更されるので、さらにConstantCHOPを配置しpx,py,pzと入力して下さい。ConstantCHOPを増やす理由は、この後繋げるExpressionCHOP のExpressionの上限が6つだからです。）

buttonRadioに繋いでいるnullCHOPをアクティブ状態に切り替え、constantCHOPの数字の所にドラッグ＆ドロップしCHOP Refarenceを選択します。（フレーム粗い...:sob::pray:）

###操作↓
![TouchDesigner 2019.19930_ C__Users_Atsushi_Desktop_CameraTransitionSample_CameraTransitionSample_CameraTransitionSample.69.toe_ 2019-12-15 04-23-34_3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514335/ce79e397-864e-54b8-44b5-f7a7a5bf3208.gif)

###操作後↓
![contantCHOP.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514335/40afce93-23a4-657c-645a-0f897951f25b.png)

##手順６　ExpressionCHOPで値を変換
ConstantCHOPにExpressionCHOPを繋ぎExprタブのExpression1の0を押すと出てくるme.inputValを消し、下記コードを入力します。入力されたfloat値（me.inputVal）をint値に変換し、文字列(str)に変更しています。me.inputValは「私に入ってきた値」、つまり「ボタンのナンバー」ですね。

```ruby:
op("cam" + str(int(me.inputVal))).par.tx
```


expressionCHOPのGroupタブにあるNum Expression（Expressionの数）を6にスライドさせ、
ExprタブのExpression2～6に先程のコードのtxをty,tz,rx,ry,rzに変更したコードを入力します。
px,py,pzも同様です。

これによって、名前の末尾がボタンの番号と同じCameraCOMPの位置や角度等の値を取得しています。
![スクリーンショット (53).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514335/4e567d52-5a72-3dce-ce41-c4127b4dfbe6.png)


##手順７　仕上げ！コントロールカメラに反映させる
次にFilterCHOPを繋ぎ、最後にNullCHOPを繋ぎます。例によってCookTypeはSelectiveにしておきます。
FilterCHOPによってヌルっとした滑らかなカメラ遷移が可能になります。

後はcontrolled_camに値を反映させるだけです！
NullCHOPをアクティブにし、controlled_camと名付けたCameraCOMPに移動し、XformタブのTranslateのx座標に
NullCHOPのtxをドラッグ＆ドロップします。選択項目が表示されるのでCHOP Referenceを選択します。
ty,tz,rx,ry,rzも同様の操作を行います。
![cameraCOMP.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514335/7c724a1c-97a8-ffc0-500e-c6d630824fde.png)


buttonRadioをアクティブにし任意の数字をプッシュすると、同じ数字のCameraCOMPの位置に遷移します。

FilterタブのFilterWidthを変更することで、遷移速度を調節できます。（値が大きいほどゆっくり遷移する）
![filterCHOP.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514335/d8b76c91-55dd-b810-2b27-72a5ce5f2e6d.png)

以上！！！！！
これでヌルっと動くカメラ遷移は完了です。[前述の記事](https://qiita.com/narumin256/items/25710e6952079e1b3348)で書かれているPathSOPと組み合わせることで、動くカメラをスイッチングすることもできます。
(GIFアニメーションだとぱきぱきしていますが、実際にはヌルヌル動いています！)
![TouchDesigner 2019.19930_ C__Users_Atsushi_Desktop_CameraTransitionSample_CameraTransitionSample_CameraTransitionSample.69.toe_ 2019-12-15 04-23-34_8.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514335/1038398f-33d6-f926-fa01-2f0c51f12051.gif)


## 最後に
サンプルファイルや記事の中で不明点等がありましたらご連絡ください。
下記にTwitter、インスタのアカウントを載せておきます！
また、この方が良くない？や、間違ってる！というご意見等がありましたら、同様にご連絡いただけたら幸いです！
[<font color="LightSkyBlue">Twitter</font>](https://twitter.com/atsh_mtsk0122)
[<font color="LightSkyBlue">Instagram</font>](https://www.instagram.com/whisroll/)