【TouchDesigner】SOPをボタン一つでSTLファイルに変換する

#こんにちは
簡単に自己紹介します。[株式会社たき工房](https://www.taki.co.jp/) のテックラボ という部署でプログラマーをしていて、インタラクティブなインスタレーションなどを作っています。個人ではTouchDesignerで映像制作やVJをしたり、HoudiniでCG制作をしています。（[Twitter](https://twitter.com/komakinex)、[instagram](https://www.instagram.com/komakinex/)）
[テックラボの制作事例](https://lab.taki.co.jp/)

#前置き
先日TouchDesigner（以下TD）で生成したオブジェクトを3Dプリンターで印刷したいと思うことがありました。
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">カメラデータのCHOPから .blend、.fbx書き出しできた！ <a href="https://t.co/3Anldi7QpY">pic.twitter.com/3Anldi7QpY</a></p>&mdash; Satoru Higa (@satoruhiga) <a href="https://twitter.com/satoruhiga/status/1328872899990626305?ref_src=twsrc%5Etfw">November 18, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">人類はついにTouchDesignerから直でProRes書き出しができるようになった <a href="https://t.co/5mm7WYxT1Q">pic.twitter.com/5mm7WYxT1Q</a></p>&mdash; Satoru Higa (@satoruhiga) <a href="https://twitter.com/satoruhiga/status/1206852979229224960?ref_src=twsrc%5Etfw">December 17, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Blenderからhclassic書き出すプラグイン書いてる なかなか似てきた <a href="https://t.co/ewnesEv2Je">https://t.co/ewnesEv2Je</a></p>&mdash; Satoru Higa (@satoruhiga) <a href="https://twitter.com/satoruhiga/status/1065390952745816064?ref_src=twsrc%5Etfw">November 21, 2018</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">TouchDesignerからUnityにチャンネルデータ書き出し、わりと汎用的な形でできた！！！<a href="https://t.co/LSBpUTe4I7">https://t.co/LSBpUTe4I7</a></p>&mdash; Satoru Higa (@satoruhiga) <a href="https://twitter.com/satoruhiga/status/1039206981460848640?ref_src=twsrc%5Etfw">September 10, 2018</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

比嘉さんのツイートを見て育ったので、以前からソフト間を横断したいという思いがあり、TDからSTLを書き出すことに挑戦しました。
今回は3Dデータの編集・変換ができるフリーのソフトウェア、Meshlabを使います。
コマンドラインから実行できるので、TD上のPythonで操作してみます。

##サンプル
ここにあります↓
[SOPconvertSTL.tox](https://drive.google.com/file/d/1cDLvCVdJP0vuBMTpT9gfFD_fjAnEOg1X/view?usp=sharing)

#本題
流れは以下の通りです。

①Meshlabをインストールする
2020.12からMeshlabserver.exeがなくなったので、2020.7を使っています。
[Meshlab-2020.07 - GitHub](https://github.com/cnr-isti-vclab/meshlab/releases/tag/Meshlab-2020.07)

②SOPをobjファイルに書き出す
TDのフォーラムでtoxを見つけました。デフォルトで書き出せてもいいのになと思います。
SOPのTypeをPolygonにして繋ぎます。
[custom .OBJ exporter](https://forum.derivative.ca/t/custom-obj-exporter/5247/8)

③書き出したobjをMeshlabで読み込み、STLに変換する
ここをPythonでやりました。

![スクリーンショット 2020-12-18 090630.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144702/0022938d-73bb-1f97-760e-ac19390623fb.png)

`Meshlabserver.exe`までの絶対パスと、書き出し時のファイル名を入力して`Convert`を押すと繋いだSOPのSTLファイルが、TDと同じ階層に作られます。


## Pythonの中身

```python:convert_to_STL.py
import os
import subprocess

def convert2stl(meshlabserverexe, input_file, output_file):
    cd = os.getcwd()
    output_path = os.path.join(cd, output_file)
    command = meshlabserverexe + " -i " + input_file + " -o " + output_file
    print(command)
    subprocess.Popen(command)
```

[MeshLabによる3Dデータ変換をCUIで実行する](https://bluebirdofoz.hatenablog.com/entry/2020/06/11/205037)
この記事によると、Meshlabserver.exeのパスが通った状態でコマンドラインで
`meshlabserverexe -i input_file -o output_file`
を叩くと変換できます。

TDでコマンドラインを叩く方法はこちらを参考にしました。
[TouchDesignerからopenFrameworksアプリを実行する(Windows)](https://qiita.com/yasuhiro0122/items/f6c5b12b676c274535fd)
`subprocess.Popen()`に`command`を渡します。

以上がMeshlabをコマンドラインから叩いて、STLファイルに書き出す部分です。

`Convert`を押すと実行されるPythonは以下です。

```python:EXPORT.py
import os
import tempfile
import convert_to_STL
import time

fd, tmp = tempfile.mkstemp(suffix='.obj')

try:
	op('OBJ').save(tmp)
	exe = parent().par.Meshlabserverexe.eval()
	output_file = parent().par.Output.eval()
	convert_to_STL.convert2stl(exe, tmp, output_file)
	print("Convert " + output_file)
	time.sleep(1)

finally:
	os.close(fd)
	os.remove(tmp)
	print("Done")
```

入力した`SOP`を`.obj`として一時ファイルに保存しておき、先程の関数に渡しています。

コマンドラインを叩いてMeshlabが一時ファイルを読み込むより先に、Pythonの処理が進んで一時ファイルが消えてしまうので、`tmp`を消す前に1秒処理を止めるようにしています。


##参考にした記事

[Meshlab スクリプトによるメッシュフィルター操作を自動化する方法](https://qiita.com/matterd/items/3a15bf30031707ab2cfd)

#おまけ

毎年M-1の予選の動画を見て、決勝進出者を予想しているのですが、今年は難しかったです。

この2組が面白かったのでぜひ見てみてください！
タイムキーパー 2回戦(5分46秒から)
https://youtu.be/GaYd0l6_ai0
エンペラー 準々決勝
https://youtu.be/_O-Wy5oDruY