4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

TouchDesignerでライフゲーム

Posted at

TouchDesignerのFeedback CHOPを使ってライフゲームを実装してみます。
study_lifegame.7.gif
ネットワーク全体は以下のようになります。
network_all.png
コンポーネントの色ごとにおおよそ次の処理を行っています。

  • 青: ライフゲームの初期状態の設定
  • 橙: ライフゲームの次状態の計算
  • 黄: 各セルの位置と色の計算
  • 青: インスタンシングを用いた描画

ここからは各処理ごとに詳細を見ていきます。

ライフゲームの初期状態の設定

network_init.png
セルを格子上に並べるため、Grid CHOPを使用して各セルの位置を求めています。縦横それぞれのセルの数はライフゲームの次状態の計算でも必要なのでConstant CHOPで管理しています。
grid1.png
各セルの初期状態を保持するChannelをNoise CHOPとExpression Chopで作成します。Noise CHOPでセル数と同じ大きさのChannelを作成して、Expression Chopで値が0・1の二値になるようにしています。今回の実装ではは0が「死」、1が「生」の状態を表しています。
noise1.png

ライフゲームの次状態の計算

network_calc.png
Feedback CHOPで各セルの状態をフレームをまたいで管理するようにし、Script CHOPで次状態の計算を行っています。Feedback CHOPの第1入力にScript CHOPの出力を繋ぎ、第2入力には先ほどに作成した初期状態の出力を繋いでいます。Feedback CHOPのResetパラメータの「Pulse」を押すと、第2入力の状態をもとにシミュレーションが実行されます。

Script CHOPには以下の次状態を計算するPythonスクリプトを記述しています。onCook関数の中で実際の計算が行われています。また、縦横のセルの数を設定するためにonSetupParameters関数内でパラメータを追加しています。

# me - this DAT
# scriptOp - the OP which is cooking

# press 'Setup Parameters' in the OP to call this function to re-create the parameters.
def onSetupParameters(scriptOp):
	page = scriptOp.appendCustomPage('Custom')
	p = page.appendInt('Width', label='width')
	p = page.appendInt('Height', label='height')
	return

# called whenever custom pulse parameter is pushed
def onPulse(par):
	return

def onCook(scriptOp):
	scriptOp.clear()

	input = scriptOp.inputs[0]
	prev_chan = input.chan(0)

	chan = scriptOp.appendChan(prev_chan.name)
	width = scriptOp.par.Width.eval()
	height = scriptOp.par.Height.eval()
	for w in range(width):
		for h in range(height):
			left = w - 1 if w != 0 else width - 1
			right = w + 1 if w != width - 1 else 0
			down = h - 1 if h != 0 else height - 1
			up = h + 1 if h != height - 1 else 0

			alives \
				= prev_chan[left + up * width] \
				+ prev_chan[left + h * width] \
				+ prev_chan[left + down * width] \
				+ prev_chan[w + up * width] \
				+ prev_chan[w + down * width] \
				+ prev_chan[right + up * width] \
				+ prev_chan[right + h * width] \
				+ prev_chan[right + down * width]

			idx = w + h * width
			state = prev_chan[idx]

			chan[idx] = 1 if \
				((state == 0 and alives == 3) or\
				(state == 1 and (alives == 2 or alives == 3))) else 0

	return

追加したパラメータには縦横それぞれのセル数を入れるようにします。
script.png

各セルの位置と色の計算

network_cell.png
各セルの位置と色を計算しています。位置はSOP to CHOPで作成したものをそのまま用いています。色はLookup CHOPを用いて0のときは黒、1のときは緑が割り当てられるようにしています。

インスタンシングを用いた描画

network_render.png
インスタンシングを有効にして、先に作成した各Channelを位置と色をパラメータに割り当てます。ここ以降は通常のインスタンシングを用いた描画と同じなので説明を割愛します。
instancing.png

終わりに

Feedback CHOPを使ってライフゲームを実装してみました。Feedback CHOPとScript CHOPを使う方法は他のシミュレーションでも有効そうです。

ただし、Operator Snippetsの「GLSL TOP」のサンプルとしてGLSL TOPとFeedback TOPを使ったライフゲームの実装があるので、実用的にはそちらを参考にしたほうがいいと思います、GPUで計算したほうが効率がいいはずなので。

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?