[TouchDesigner]インスタンスにライフタイムを実装する

![レコーディング-2024-09-25-102202.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152366/f7fb74b8-366d-e417-94d9-e05ed205f245.gif)

## はじめに
TouchDesignerのGPUインスタンス機能は軽くて便利です
でもライフタイムがないのでライフタイムを使ったいかにもパーティクルっぽい動きを作りたいときに困ります
今回はどうやったらライフタイムが実装できるのか考えてみます

以下からサンプルファイルをダウンロードできます
サンプルファイルをみながら読んでみてください
サンプルファイル: [.toe](https://github.com/takashikawamura/TD_particle/blob/main/Particle%20LifeTime%20.toe)
## ライフタイムとは
パーティクルのひとつひとつが生成されてから消滅するまでの時間です
煙や炎や水しぶきなどを表現したいときなどに便利です
大きさや色の変化をライフタイムで制御したり、生成と消滅を繰り返せばひたすら発生させ続けてもぜんぜん大丈夫だったり
TouchDesignerを使っているといわゆるパーティクルっぽいものもGPUインスタンス機能で作ることが多いのですが、ライフタイムという考え方がないためたまに困ることがあります
## サンプル紹介
こんなものを作ります
![レコーディング-2024-09-24-183529.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152366/944804ab-60b2-c932-0324-f7f2832507c6.gif)
わかりやすくライフタイムを使ってるシンプルなパーティクル表現です
- エミッター（パーティクルが発生する場所）が原点にある
- 生成～消滅までの間にだんだん小さくなる
- 生成～消滅までの間に黄色→水色→青と色が変わっていく

ざっくりこんな特徴があります
## ライフタイムのしくみ
さて、さっそく中身をみていきます
![レコーディング-2024-09-24-185844.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152366/ce8e13dd-2f52-52ed-c061-2331174bf76c.gif)
サンプルファイルのここ↓
/project1/LifeTime/LifeTime
にライフタイムの機能が入ってます
#### エミッターのポジション指定
パーティクルの発生位置を指定しています
(0,0,0)の真っ黒なテクスチャを指定しているのですべてのパーティクルが原点から生成するようになっているのがわかります
![スクリーンショット 2024-09-24 213252.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152366/3bad809d-f42e-4014-23df-f28313ad7136.png)

例えばここに(0.5,0,0.5)のエミッターを入れてみると...
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152366/1a83cc83-6225-b5b5-16e4-ff4c55ebb0a3.png" width="512">

こんなふうになります
![レコーディング-2024-09-24-214850.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152366/14e61861-8323-0707-a9cb-ab45512e8361.gif)

### FeedBack（繰り返し算）を使ってライフタイムのループを作る

全体はこのようなふうに組まれています
![スクリーンショット-2024-09-24-215737.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152366/2daa301f-f301-fa4c-9c5a-11751c23784a.png)


![スクリーンショット-2024-09-24-220419.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152366/686d93fd-a760-3da2-a0e6-7685ab2c4d0c.gif)

まずはfeedbackのボックスから
ランダムなノイズ(①)、selectTOPでとってきた初期位置(③)、しきい値1のthresholdTOP(④)を用意し、matteTOP(⑤)に対して上から③、②、④の順番で入力します
その結果をaddTOP(⑥)につないでいます

### ライフタイムの数値を設定する
もうひとつのaddTOPの入力は以下のボックスからとられています
![スクリーンショット-2024-09-25-091323.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152366/40ac60f2-23f4-32cf-39f3-bb48b15607bc.png)

constantCHOP(⑦)のtimestepは”1/me.rate”というexpressionが書かれています
1フレームに何秒かかるかという値で、一般的にdeltaTimeと言われるものです
フレームレートが変動してもfeedback処理の計算結果が変わらないようにするために使われます
lifetimeには”1/parent().par.Lifetime”と書かれています
上の階層でライフタイム（パーティクルの寿命）を秒数で指定しているのですが、それをあつかいやすいように「ライフタイム全体を1としたとき、1秒間に進む割合」になるよう計算しています
varianceは各パーティクルの寿命のバラつき具合です

constantTOP(⑧)のrに”op('constant1')['timestep']*op('constant1')['lifetime']”と書かれています
これは後ほどfeedbackされるときに毎フレーム加算し続けて寿命の秒数が経過するとちょうど1に達する数値(秒)です
noiseTOP(⑨)はvarianceで設定した数値だけライフタイムにバラつきを作っています
その値をfeedbackのボックス内のaddTOP(⑥)につなげます

noiseTOP(①)の後ろにfeedback(②)を挟んで、addTOP(⑥)との間で処理を繰り返します
ライフタイムを設定しているボックスからの値が毎フレーム徐々に加算されて1に達するとthresholdTOP(④)が1フレームだけ1をmatteTOP(⑤)に送り、それを受けたピクセルはselectTOP(③)の0を受け取るので値がリセットされ再び0から加算される、といった仕組みです
### 初期位置に戻す設定
残りのボックスは初期位置を送るしくみです
![スクリーンショット 2024-09-25 095733.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152366/531ad4cb-3075-b005-d884-8275d61e1960.png)
仕組みはシンプルです
先ほどのfeedbackのthresholdTOPでリセットするために使っていた値で初期位置を乗算し、ライフタイムに到達したらただ初期位置を送る仕組みです


ライフタイムを作り出す仕組みは以上です
それをどのように活用するのか見ていきましょう
## ポジションへの活用
エミッターから常に吹き出し続けているように見えるようにするために以下のような組み方をしています
初期位置から始まって徐々にノイズとポジションYが加算され、死んだら初期位置に戻る、といった簡単な動作です
![スクリーンショット 2024-09-25 100552.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152366/6ea24dc9-f672-f2dd-2330-15436025506f.png)
通常TouchDesignerでおこなうインスタンスのポジションアニメーションに「死んだら初期位置を送る仕組み」を足してみた感じです
## 年齢を使った表現
生まれてから死ぬまでのリニアな数値はさまざまな活用方法が考えられます
今回はシンプルにスケールとカラーにあててみました
スケールはだんだん小さくなり、
色は黄色から青へ変化していきます
![スクリーンショット 2024-09-25 101500.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152366/80ffdd70-7747-696a-8f5f-72675683bae4.png)
ライフタイムを取ればこのような表現もごく簡単に作り出せます

## おしまいに
パーティクルにおけるライフタイムを使った表現の活用方法をいろいろとためしてみてください
使い方を忘れたらたまにこの記事に戻ってきて思い出すなどするときに使ってもらえるとうれしいです