feature image

2023年7月11日 | ブログ記事

BlenderのGeometryNodesでBrainf*ckを実行しよう

@d_etteiu8383です。BlenderのGeometryNodesでBrainf*ckを実行したので、BlenderのGeometryNodesでBrainf*ckを実行する話をします。

Blenderとは

blender.org - Home of the Blender project - Free and Open 3D Creation Software
The Freedom to Create

Blender is the free and open source 3D creation suite.
https://www.blender.org/about/

無料の3DCG制作ソフトウェアです。
いろいろできるので3DCG制作以外のために使用している人もいます。

GeometryNodesとは

Geometry Nodes(ジオメトリノード) — Blender Manual

ノードベースの操作でオブジェクトのジオメトリを変更する
https://docs.blender.org/manual/ja/dev/modeling/geometry_nodes/introduction.html

ためのシステムです。
いろいろできるのでジオメトリの変更以外のために使用している人もいます。

僕はというと、シューティングゲームを作ったりしていました。

shooting game with blender geometry nodes simulation zone...#Blender #b3d #GeometryNodes pic.twitter.com/57YZDCqCgs

— eyemono.moe / でって (@eyemono_moe) June 28, 2023

Brainf*ckとは

Brainfuck - Wikipedia

Brainf*ckは、1993年にUrban Müllerによって作られたプログラミング言語です。いわゆる難解プログラミング言語の一つとして知られており、その命令セットはたった8つの文字から成り立っています。それぞれの文字は、メモリの操作やデータの変更などの機能を持っています。

命令 動作
> ポインタをインクリメントする
< ポインタをデクリメントする
+ ポインタが指す値をインクリメントする
- ポインタが指す値をデクリメントする
. ポインタが指す値を出力に書き出す
, 入力から1バイト読み込んで、ポインタが指す先に代入する
[ ポインタが指す値が0なら、対応する]の直後にジャンプする
] ポインタが指す値が0でないなら、対応する[の直後にジャンプする

引用: https://ja.wikipedia.org/wiki/Brainfuck#Brainfuckの言語仕様 2023/07/11

これらの命令セットを組み合わせることで、プログラムを作成します。

例: ++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.(引用: https://esolangs.org/wiki/Brainfuck#Examples 2023/07/11)

上の例では、Hello World!が出力されます。

仕様がシンプルであることから、様々な場面で実装に挑戦する人が生まれています。
初代DOOMみたいなアレです。

この記事の目標

BlenderのGeometryNodesを用い、Brainf*ckのインタプリタぽいものを作る。

Why?

Why not?

できるので、やります。単純にGeometryNodesの使い方を勉強したかったのもあります(そろそろShaderNodes芸人辞めてGeometryNodes芸を身につけたかった)。

【Blender】1ポリゴンで(大嘘)ポリゴン2を作る【Vector Displacement】
こんにちは、@d_etteiu8383です。この記事はtraP夏のブログリレー9月6日の記事です。この記事ではBlenderにおけるVector Displacementとその悪用を紹介します(悪用がメインですので前半は飛ばしていただいても構いません)。 突然ですが本日9月6日が何の日だかご存じでしょうか?そうです、つい先日NonSugarとしての初のアルバム『Tasting NonSugar』を発売したことでも有名な真中のんさんの誕生日ですね。 プリパラ 第1話「アイドル始めちゃいました!」 彼女はアニメ『プリパラ』の登場人物の一人ですが、このアニメは3DCGを利用したライブシーンが特徴…
【Blender】シェーダーノードでノイズテクスチャをループさせる【Shader Nodes】
この記事の目標は、Blenderのマテリアルノードで「テクスチャを上下左右にループさせて格子状にタイリングする」ことです。上図のようにノードを組むことで、[0,1]*[0,1]のいわゆる通常のUV座標に対して上下左右にシームレスにつながるノイズテクスチャをマッピングすることができます。

戦略

Blender 3.6 LTSから正式実装されたSimulation Nodesを用いることで簡単に実装できそうです。

なお、今回の実装では最適化などは行わず、仕様通りの動作を素直にノードで再現していきました。Blenderのアニメーション再生時に、(約)1命令/1フレームのペースで命令を実行することとします。

Simulation Nodes

Simulation Zone — Blender Manual

Simulation is defined by the “Simulation Zone”, connecting the Simulation Input and Output.

SIM IN
On the first frame, the inputs of the Simulation Input node are evaluated.
In later frames the inputs aren’t evaluated anymore, the node outputs the result of the previous frame.

SIM OUT
The Simulation Output node saves the state for the next frame.
https://www.blender.org/download/releases/3-6/

Simulation Nodesは、シミュレーションの入力と出力を定義するノードです。
Simulation Inputノードへの入力は、最初のフレームでのみ評価され、以降のフレームでは前のフレームの結果が出力されます。Simulation Outputノードは、次のフレームのために状態を保存します(保存しつつ出力もする)。

シミュレーションゾーンによる数値の加算処理例

例えば上記画像のようにノードを組むと、以下のように動作します。

  1. 1フレーム目:
    1. "シミュレーション入力"ノードのソケットへの入力が評価される
      • ここでは"値"ノードからの10.0が評価される
    2. "シミュレーション入力"ノードのソケットの出力に、1.0を加算する
      • 10.0 + 1.0 = 11.0
    3. "シミュレーション出力"ノードのソケットに11.0が保存される
    4. "シミュレーション出力"ノードのソケットから11.0が出力される
  2. 2フレーム目:
    1. "シミュレーション入力"ノードのソケットの出力は、前のフレームで保存された11.0になる
    2. "シミュレーション入力"ノードのソケットの出力に、1.0を加算する
      • 11.0 + 1.0 = 12.0
    3. "シミュレーション出力"ノードのソケットに12.0が保存される
    4. "シミュレーション出力"ノードのソケットから12.0が出力される
  3. ...

今回の実装では、上記の動作を利用してフレーム間でのメモリ状態の保存を行います。

メモリの再現

Brainf*ckのインタプリタ実装にあたって最低限必要な要素は以下の通りです。

これらに加え、ループ処理等で必要な情報も含めて、全ての情報をジオメトリの属性として保存します。

Attributes(属性) — Blender Manual

今回は、事前に用意したPointの属性を利用して、メモリ等を再現します。下記画像は、今回実装したBrainf*ckのインタプリタの動作後のPointの属性です。数百個のPointを用意し、各点を配列の要素のように扱っています。

スプレッドシートエディタにおける属性の表示例(`Memory`, `Pointer`, ...等が属性)

実装

(実装の説明いる????)実装方針だけ示します。最終的に作ったblendファイルを以下に置いておきます。自由に動かして遊んでみてください。WTFPLで公開します。Brainf*ckだし。

Brainfuck
今回実装したGeometryNodesを含むblendファイルです
download-circle

メモリやポインタ等の情報を、Bufferソケットにつないでいるジオメトリに属性として保存し、このジオメトリをシミュレーションゾーン内で毎フレーム更新しています。

今回の実装の模式図(ループ処理等を省略しています)

Bufferには以下の属性を持たせています。

GetCommandグループで、入力プログラム文字列から現在のフレームに対応する命令を取得しています。

この命令に応じて、pointerCommandMemoryCommandグループ内で、Bufferの属性を更新しています。

画像では省略していますが、Bufferの更新をスキップすれば命令の実行も一時停止できるので、Nフレーム毎の実行等も可能です。

入力ストリームはきれいな実装が思いつかなかったので今回は実装していません。誰も怒らないと思います。

動かしてみる

愚直に実装したおかげで"1フレーム1命令の実行"となっているため、メモリやポインタ、命令位置をいい感じに可視化するといい感じになります。

命令を読み取るロボットっぽい娘やメモリっぽいものを作り、属性として保存している情報を使用してジオメトリを追加・移動することで、以下のようなアニメーションを作ってみました。

シミュレーションゾーンでBrainfuckのインタプリタ実装#Blender #b3d #GeometryNodes pic.twitter.com/norqVmdiR6

— eyemono.moe / でって (@eyemono_moe) July 6, 2023

なお、文字コードから文字列への変換には、(少しずるいですが)以下のようなノードを用いています。

文字列スライスを用いてコードに対応する文字を1つ取り出しています(範囲外/制御文字はすべて半角スペースで代用)

いかがでしたか?

Pythonでスクリプトを書いたほうが良い

d_etteiu8383 icon
この記事を書いた人
d_etteiu8383

グラフィック班とゲーム班とSysAd班所属 いろいろ活動しています

この記事をシェア

このエントリーをはてなブックマークに追加
共有

関連する記事

2023年11月21日
School Breakin' Tag -新感覚おにごっこ-
s9 icon s9
2023年4月17日
ポケモンを飼いたい夢を叶える
tqk icon tqk
2023年3月20日
traPグラフィック班の活動紹介(Ver.2023)
NABE icon NABE
2022年4月7日
traPグラフィック班の活動紹介
annin icon annin
2021年3月19日
traPグラフィック班の活動紹介
NABE icon NABE
2024年3月22日
traPグラフィック班の活動紹介2024
haru10 icon haru10
記事一覧 タグ一覧 Google アナリティクスについて 特定商取引法に基づく表記