TouchDesigner Exprimentalに追加されたJSON DATを使ってみた

wrnchAIが入ったのが話題になりがちなTouchDesignerですが、同時にJSON DATも入ったの知ってました？
他アプリケーションで吐いたデータを使うときに、いままでTDのためにわざわざCSVで書き出してたのが結構楽になると思うのでとりあえず使ってみました。
本記事で使用したバージョンは2020.40290です。

Experimental:JSON DAT(公式ドキュメント)
https://docs.derivative.ca/Experimental:JSON_DAT

Experimental版のTouchDesignerのDLはこちら
https://derivative.ca/download/experimental

今回はサンプルとして、このページのスケルトンデータを読んで表示してみます。
https://kinectron.github.io/docs/example-skeleton-images-azure.html

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr"><a href="https://twitter.com/hashtag/TouchDesigner?src=hash&amp;ref_src=twsrc%5Etfw">#TouchDesigner</a> experimentalに追加されてたJSON DATを使って <a href="https://t.co/PlE0ZPFnSB">https://t.co/PlE0ZPFnSB</a> ここのモーションデータを表示してみた。 <a href="https://t.co/dH6MAAcdHN">pic.twitter.com/dH6MAAcdHN</a></p>&mdash; 岩谷成晃 (@nariakiiwatani) <a href="https://twitter.com/nariakiiwatani/status/1295265658259689473?ref_src=twsrc%5Etfw">August 17, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


# ファイルからの読み込みはFile in DATで

書くほどでもないことですが、JSON DATはあくまでテキストのパーサなので、ファイルに書いてあるJSONデータを使いたい時は通常通りFile in DATで読み込んでから渡す必要があります。
[NDJSON](http://ndjson.org/)とか読むときに便利そうですね。

![スクリーンショット 2020-08-17 16.56.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16556/7746b8b5-7f21-f908-f373-723529b25a30.png)

# DATの出力は文字列。データはopアクセスもしくはevalで

JSONをパースした結果をXML DATのようにTableによしなに並べてくれるみたいな機能はなさそうでした。
DATからの出力はFormat(Pretty print的な)するかどうかを選べるだけで、あくまでひとつのJSON文字列であるようです。

パース結果は、`dat.result`で取り出して利用することができます。
このリンクで言っている`JSONable Python Object`にあたるものだと思います。
https://docs.derivative.ca/TDJSON

一応、resultをオペレータの[Storage](https://docs.derivative.ca/Storage)に入れて、Examine DATでTable化することはできはします。
![スクリーンショット 2020-08-17 22.32.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16556/61b2f2f3-0d4a-5f8e-111d-9f19f1d41ad2.png)

# トップレベルがArrayで包まれる

これまでのスクショで気づいた方もいるかも知れませんが、元データがJSON DATに入ると一層深くArrayで包まれます。
JSON DATの出力をさらにJSON DATに食わせるともう一層追加されます。

![スクリーンショット 2020-08-17 17.05.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16556/35a39367-6f75-5dd0-c868-0a6b38e26b4a.png)

[JSON DATのリファレンス](https://docs.derivative.ca/JsonDAT_Class)を読むと、パース結果のオブジェクトへのアクセスは

- `DAT.source`: 入力のパース結果
- `DAT.results`: `JSONPath Filter`パラメータでフィルタリングされた結果
- `DAT.result`: `DAT.results`の最初の要素

の3通りが用意されているようです。

おそらくこの`result`と`results`が常に存在することを担保するために、Arrayで包む仕様になっているのかもしれません。
じゃあ`DAT.results`の方いらんくね？とも思うんですが、この辺まだよく捉え切れてなくてなんとも言えないです。

Python Objectはevalに突っ込むこともできます。

![スクリーンショット 2020-08-17 17.25.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16556/9004bffe-1468-17cd-0d3e-63aeb99abd20.png)

結果がArrayの場合、JSON DAT => Eval DAT => Convert DATでTableに変換すると扱いやすかったです。

結果がObject(dict)の場合、さっき書いたようにStorageに突っ込むか、ちまちまスクリプトを書くかしか扱う方法がなさそうで、それだといまいちJSON用オペレータが組み込まれたインパクトが薄いなーと思っています。

# フィルタリング

ということで元データがどんな形であれ、最終的にArrayになるようなデータ抽出をしたいわけですが、それを可能にするのがこのフィルタリング機能です。

[JSONPath](https://docs.derivative.ca/JSONPath)という記法で抽出するデータを指定します。
![スクリーンショット 2020-08-17 23.36.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16556/c908b2cc-9f37-91cc-793c-0349dc27eaac.png)

ここでなんとなく`DAT.results`にも意味があるような気がしてきましたが、なんか掴みどころがなくてやっぱりまだよくわかってません。

# スケルトンデータ読み込み

ここまで書いて力尽きてきたのでGitHubにあげてリンクするだけにします。。
https://github.com/nariakiiwatani/TouchDesignerEx_JSONDAT_sample

ざっくり解説すると

- JSONファイルを読む(File in DAT)
- 各関節のカメラからの3D座標と回転（Quaternion)を1フレーム毎に取り出せるようJSONPathを記述(JSON DAT)
- 回転(Quaternion)をインスタンシングで使えるようにオイラー角に変換(Script CHOP)
- 各関節の1フレーム分の位置と回転をCHOPひとつになるようにShuffleとかSelectとかでデータをいじる
- それをGeometry COMPに突っ込んでインスタンシング

ということをやっています。