Toucanバーチャル博物館
VRML図鑑 3DCG 展示室   開発日誌 お問い合わせ

トコちゃんの修行日誌 2025年9月

9月30日 流れのボクセル化

流れを一旦パーティクルにしてしばらくシミュレーションしてから、ボクセル化してみました。シミュレーションで密度が計算されているので、その値を取得してボクセル値に変換しています。

流れ1

上が元の流れ、下がシミュレーション後。若干流れがスムーズで下流に水が溜まり気味です。

流れ2

上が元の流れ、下がシミュレーション後。左が下流。岩の周りなど水際がガタガタです。ボクセル化の工夫が必要ですね。 

流れ3

左が元の流れ、右がシミュレーション後。下が下流。流れの緩急が強調される感じです。やはり水際がガタガタです。

もしかしたら、リアルタイムでのアニメーションが可能かもしれません。試してみます。

9月25日 高速化

Burstコンパイルとジョブで75FPS(1秒75描画)で描画できるようになりました。

ChatGPTにGPU(コンピュータシェーダ)で高速化をお願いしたのですが、どうも複雑すぎて無理みたいで、使っていなかったHeightマップでの衝突判定や、衝突用3Dテクスチャを事前に作成して処理する方法など提案してきました。

しかたなくジョブで高速化を試したのですが、十分速くなりました。

BurstJob

これはパーティクルの半径を半分、パーティクル量は4倍で試してみたのですが、それでも20FPSで動きます。細かすぎて勢いあまって盛り上がってしまったりしています。

4倍のパーティクル

9月23日 実験成功

上から

横から

ほとんどChatGPT-5に任せて、突貫工事で実験してみました。思っていた以上にうまくいっています。シミュレーション結果もBlenderのFluidに十分に近い感じです。

切り出された範囲だけのシミュレーションなので3.5FPS(1秒3.5描画)で動いています。C#なので、処理をバーストコンパイルまたはGPU(コンピュータシェーダ)で高速化すれば十分動作しそうです。

最初の状態は水は下流へ流れて溜まって動かなくなっていました。

ここで工夫が必要になりました。流れ込んでくる水の量と、流れ出す量は同じと仮定します。何処を切り取っても水の量は時間とともに変わる訳ではないので正しいと思います。

そこで境界でのクリッピングを止めて、外にでたパーティクルを流れ込んでいる境界に均等に再配置してみました。

これで試してみると、下流の水は堰を切って流れ出し、上流から噴水のように吹き出しました。そりゃそうですね。

そこで境界面から1マスだけ元の水流の速度を維持するように補正したところ、かなりうまくいっています。

9月22日 キーボード買い替え

2023年4月に購入のロジクールK835GPRメカニカルキーボード、反応しないキーがH,1,9,Esc,Fn,Insertなどあまり使用しないキーを中心にいくつかでてきていたので買い替えました。グリグリ、何度か押すと辛うじて入力できるので騙し騙し使っていたのですが・・・3Dモデリング作業なら我慢できていたのですが、プログラム作業となるとストレスが溜まる。

購入したのはREALFORCE R3S キーボード、静電容量無接点方式とかで長寿命らしい。64歳誕生日、私の寿命より長いかもしれない。そんな歳になりました。 

9月19日 プロンプト

参考にプロンプト

TryGetGroundMapContactの代わりにlandscapeのgroundVoxelsの値で衝突判定をして、groundNormalsの値から法線を計算するメソッドを考えてください。

ここから回答

GitHub Copilot
了解しました。GeologyMap.TryGetGroundMapContact の代わりに、Landscape が持つ groundVoxels と groundNormals を使って接地点と法線を求めるメソッドを追加します。併せて使いやすいように GameManager から Landscape を公開し、FluidSim3D の衝突解決で新メソッドを使うように差し替えます。

ポイント
• スカラー場は 0 が等値面(地形表面)。負が内部、正が外部(既存の Marching 実装と整合)。
• スカラーサンプルは千鳥配置(stagger)とラッピングを考慮した3次元トリリニア補間。
• 法線は groundNormals のボクセルごとの値をトリリニア補間して取得。
• 接地点は現在位置から補間法線方向へ小ステップで符号反転を見つけ、2分探索で 0 交差点に収束。

以下作成されたコードが続く

参照したgroundNormalsが私の間違いで符号が反転していました。そのため、負が内部と解釈したようです。ポイントの2番目、千鳥配置(stagger)については、私が独自に命名し追加した処理で菱形にひしゃげたグリッドを2段毎にずらしてなるべく直方体に形をちかづける処理です。

私のコードでしか使われていない処理、それも数か所、それの意味をくみとってコードに組み入れています。それも数秒で解釈している。

作成されたコードはそのまま動作したので、あらためてすごいと思う。もう人間を超えている。頼れる私より優秀な部下。 

9月17日 ChatGPT-5に丸投げ

ボクセルデータで衝突判定

複雑な処理なのでGPT-5に丸投げではこんな感じです。地面には衝突しているので、法線に問題があるのかな?

処理は1FPS(1秒1描画)まで落ちました。

<追記>

若干の湧き水

若干の湧き水のような水底の流れが発生していますが、まあこのぐらいならいいでしょう。地面との摩擦(粘性抵抗のようなものだろうか)あっても良さそうなので残すことにしました。

GPT-5がボクセル値が負の場合を地面と勘違い(と言うかそこまで指定していなかったのですが)しただけでした。法線の計算もそのため反転していました。

昨日のHeightマップ版をみると、だいぶ水漏れしていたようです。ポリゴンが粗いので深いところが潰れてしまっているのかもしれませんが、地形のボクセル値を使って衝突判定しているので、地面にしっかり沿っています。

自分でコーディングしていたらたぶん数日はかかっただろう。これで一カ月1600円は安い。

9月16日 Heightマップで衝突判定

Heightマップ(高さ画像)で衝突判定してみました。

7FPS(1秒7描画)で動いています。

地面の法線(傾き)は計算コストを下げるため、Heightマップから事前に計算して法線マップを作成しています。

判断材料が高さだけなので真上から見た状態で衝突をしらべることになります。なので崖を横に移動すると、位置が大きく上がったり下がったりします。

それが原因だと思われますが、水中なのに斜面を水が下り、底中央で湧きあがります。深いところで大きく盛り上がっている。

摩擦無し

対策として地面との摩擦を加えてみました。

摩擦有り

だいぶ抑えられ、水面が平らになったのですが、滝ができてしまった。

なんとかなりそうです。 

もう一つ、地形を作成しているボクセルデータで衝突判定する方法を試してみます。データはHeightマップより粗くなりますが、立体なので今回のような問題は発生しないと思います。若干処理が重くはなりますが・・・

9月15日 GameObject (Hybrid) 前途多難

Hybrid

地形の衝突判定をEnitityのコライダーで処理しようと、色々と試したのですが(GPT-5君に頼んで)、どうしてもHitせず(地形として認識しない)、数日1行もプログラムが進みませんでした。

もう、あきらめようかとも思ったのですが、一番簡単な手順、GameObjectで地形をプレハブとして保存、それをサブシーンに配置して自動でEnitityに変換してテストしたら、なんとか動きました。

あまりに処理が重いので20分の1にパーティクル数をへらし、水たまりができました。1フレーム10秒ほどかかります。

前途多難

地形のような複雑なポリゴンで数万個のパーティクルとの衝突を計算するのは無理のようです。

勉強をかねてEnitityでの物理演算unity.physicsを理解しておこうと思いますが、違う方法で考えます。 

<追記>

Enitity用のPhysicsColliderへ地面のメッシュを登録する度に物理演算用の事前処理が必要なのでしょう。スムーズなスクロールができません。Unity組み込みのPhysXの方が軽いです。

物理演算をEnitity用のunity.physicsへ移行を考えていましたがあきらめました。

コンポーネント

地形をプレハブから表示を削除してコライダーだけにしても、自動的に追加されるコンポーネントがこれだけあります。自前のはLandColliderTagだけです。地面水面を種別する目的。

コードだけで作成していたときはLocalTransformとPhysicsColliderの二つだけで試していて失敗していました。プログラムの流れは合っていたようなので、SimullateとかPhysicsWorldIndexとかが必要だったのかもしれません。 

9月10日 GPUからC#へ

ボールプール

まるでボールプールですね。

Copilot+GPT-5にお願いして、GPU(コンピュータシェーダ)の処理をC#に書き直してもらいました。ほぼ完璧に書き直してくれます。7つのステップで処理されてて1つ1つC#に変換してテストしてみました。

C#だと軽い処理で150ms、重い処理だと1000ms(1秒)以上処理に時間がかかります。GPUだと7ステップ全部で0.5ms。GPU処理はとんでもなく速いんですね。

あまりに重い処理なので全部C#で実行してみてはいませんが、たぶん5000ms(5秒)はかかるでしょう。GPUが1万倍速いわけです。

幸いなことに密度や圧力、粘性などの計算のあと、最後に速度から位置を計算して衝突判定しています。ここだけC#のバーストコンパイルで高速化すれば、経験上100倍ほど速くなるので、150msが1.5msに短縮されるでしょう。地形との衝突で処理が重くなっても、なんとかなりそうな気がします。

GPUで処理し、衝突判定だけC#で処理。こんな方針で進めてみます。

衝突判定に必要なUnity組み込みの物理演算PhysXはバーストジョブから使用できず、Unity.Physicsパッケージを使用するようです。Entityとしてメッシュコライダーなど登録する必要があるようで、プレイヤーの移動を改良する必要がでてきました。幸いなことにCharacterControllerの機能はほとんど使っていないので、なんとかなるかな。

まだ作っていない木や岩などの配置もEntityベースになりそうです。草はEntityで配置しています。

9月9日 造成 Landscaping

造成

アクションメニューを選択して、地形の造成ができるようになりました。マーチング四面体用のボクセルデータ用と、高さマップ(HeightMap)や流れマップ(FlowMap)の2Dデータ用。

マップが狭く感じます。すぐにクリップ面にとどいて編集できなかったりします。ゲームの要素として扱うには色々と工夫が必要そうです。

リアルタイムの水の流れのシミュレーションに挑戦してみようかと思います。参考にするのは

Fluidシミュレーション

Coding Adventure: Simulating Fluids

GPU(HLSL)でシミュレーションされていて0.5ms程度で動作しています。すごい。

ボックスのような単純な形ではないので、工夫が必要です。後の続編で小さな地球の海をシミュレーションするときに、地形を3Dテクスチャに変換していました。

そこまですると色々とややこしい。ただでさえ、流れ込み、流れ出し部分でかなりの補正が必要になりそうです。

マップがスクロールしなければ時間的に余裕ができるので、ジョブシステムで同様の計算で試してみようかと思います。目標はこのぐらいの解像度(パーティクル)で15ms。

DOTS(Data-Oriented Technology Stack)なんかも利用することになるのかな?

9月8日 健康診断診察

逆流性食道炎GradeM

胃底腺ポリープ

便潜血検査陽性で、大腸CTを受けました。

そのCT結果

大腸:盲腸にポリープ疑い

肝臓:嚢胞疑い

左副腎:副腎皮質線種疑い、ハゲの進行はこれが原因?

・・・執行猶予で来年、腹部CT+ホルモン採血予定。 

../toucan/TocoDiaryJ.html