インクを水に落とすインタラクティブシミュレーション(Stable Fluids)
概要
インクを水に落とすシミュレーション(Stable Fluids)にマウス操作によるインタラクティブな制御と、詳細なパラメータ調整機能を追加したもの
使い分け
動作を体験したい場合:機能に優れた高い本アプリケーションを推奨
内部を理解したい場合:実装がシンプルな通常盤を推奨
https://scrapbox.io/files/695bb08465e935b781db2d0e.png
公開
動作確認(webアプリ):Ink in Water Interactive|Claude Artifact
ソースコード:ink_in_water_interactive.jsx|GitHub Gist
操作方法
基本操作
マウスクリック:クリックした位置(x座標)からインクが落下を開始
ドラッグ:マウスを押したまま動かすことで、インクの落下位置を変更
マウスリリース:インクの落下を停止
設定メニュー
画面右上の歯車アイコンをクリックすることで、設定パネルが開く。
【リセット機能】
流体をリセット :現在のシミュレーション状態をクリアし、流体場を初期化
パラメータをリセット:すべてのパラメータを初期値に戻す
【調整可能なパラメータ】
Buoyancy(浮力):-0.5 〜 0.5
負の値でインクが沈み、正の値で浮く。
初期値:-0.15
Velocity Dissipation(速度消散率):0.95 〜 0.999
値が大きいほど流れが長く持続する。
初期値:0.995
Density Dissipation(密度消散率):0.95 〜 0.999
値が大きいほどインクがゆっくり消える。
初期値:0.997
Ink Radius(インク半径):0.005 〜 0.05
インク滴のサイズを制御。
初期値:0.012
Velocity Strength(速度強度):-2.0 〜 2.0
インクに与える初期の下向き速度。
初期値:-0.8
実装
画面全体を覆う平面に対して計算と描画を行う。
流体の状態は複数のバッファに分けて保存され、各バッファを順番に更新することで時間の進行を表現する。
流体計算
毎フレーム、次の処理を順に行う
1. インクと速度の追加(splat)
マウスが押されている間、カーソル位置にインクの量(density)と初期的な動き(velocity)を加える。
インクの追加は連続的に行われ、マウスを動かすことで落下位置を変更できる。
2. 浮力の加算(buoyancy)
インクの量に応じて上下方向の力を速度に加え、水中での動きを作る。
浮力パラメータにより、インクが沈む/浮く挙動を制御できる。
3. 速度の移動(移流 / advection)
現在の速度を使って、次の時間の速度分布を計算する。
ここでは計算が壊れにくい方法(Semi-Lagrangian)が使われている。
速度消散率パラメータにより、流れの持続性を調整可能。
4. 発散の計算(divergence)
流れが広がったり縮んだりしている度合いを数値として求める。
5. 圧力の計算(pressure)
発散を打ち消すための圧力を反復計算(Jacobi法、30イテレーション)で求める。
6. 速度の補正(pressure gradient subtraction)
圧力の差を使って速度を修正し、体積が保たれるようにする。
7. インクの移動(密度の移流)
修正後の速度に従って、インクを流れに沿って移動させる。
密度消散率パラメータにより、インクの消失速度を調整可能。
描画処理
密度の大きさをもとに色を決め、水の背景色と合成して表示する。
インクの色は虹色効果(palette関数)により視覚的に魅力的な表現が得られる。
ビネット効果により画面周辺を暗くし、中央に視線を集める。
マウスインタラクション
マウスイベントをリアルタイムに処理し、クリック位置とドラッグ軌跡を正規化座標(0.0〜1.0)に変換して流体シミュレーションに反映する。
mouseRef を使用してフレーム間でマウス状態を保持し、毎フレーム isDown フラグを確認してインク追加の有無を判定する。
パラメータ管理
React の useState フックを用いてパラメータ状態を管理。
パラメータ変更時には useEffect の依存配列により自動的にシミュレーション全体が再初期化され、新しい設定が適用される。