見出し画像

20 行のプログラムで水面のアニメーションを作る

 見た目を気にしなければ、20 行も必要なく 280 文字でインタラクティブな水面シミュレーターは記述できる。

このプログラムでは配列 P に水面の高さを入れると、あとは自動的にシミュレーションを行い、水面の高さを計算してくれる。これはそこそこ真面目な水面シミュレータであり、nVIDIA が出しているホワイトペーパーの方法を実装したものである。

https://http.download.nvidia.com/developer/SDK/Individual_Samples/DEMOS/Direct3D9/src/VertexTextureFetchWater/docs/VertexTextureFetchWater.pdf

以前解説記事も書いた気がするので、検索してもらえると出てくるかもしれない。

 今回は上から何か落ちてきて、それが水面に当たり波が起きる様子をプログラムで実装してみた。X が落ちてくる物体(四角形)の横方向の位置であり、Y が縦方向の位置である。変数 V が落下速度であり、この V は一定速度で増加しつづけるため、透過速度運動となっている。

P=O=[0]*52
def setup():size(450,255);noStroke();fill(10,120,200)
X=Y=256
V=1
def draw():
 global O,P,X,Y,V;background(-1);q=[0]*52
 if Y>255:
     X=int(random(52));Y=0;V=2
 square(X*9,Y,10)
 Y+=V
 V+=.2
 if Y>99-P[X]:
    P[X]+=randomGaussian()*2
 for i in range(51):
    q[i]=(1.99)*P[i]-.99*O[i]+.4*(P[(i+50)%51]+P[(i+1)%51]-2*P[i]);
    u,v=99-P[i],99-P[i+1]
    s=i*9
    t=s+9    
    quad(s,u,t,v,t,255,s,255)
 O=P;P=q

中央付近にある、P[X]+=randomGaussian()*2 にて、水面の位置を変化させている。水面が高くなれば、その部分の水の量が増えることになる。逆の場合は減ることを意味する。そのため、これは水量を変化させることに他ならないが、randomGaussian は平均 0 の正規分布に従う乱数を発生させるため、長い時間でみると統計的には全体の水量は変化しない。でも、短期的には偏りが出るため、水位が上がったり下がったりする。

これを防ぐには、増えた水量を記録しておき、水量の増減を調整するのが良いと思うが、今回のプログラムには入れていない。

 たった 20 行のプログラムではあるが、水面のシミュレーションができることを今回は示してみた。実際の動画は以下の tweet を見てもらえれば、と思う。


この記事が参加している募集

私の作品紹介

この記事が気に入ったらサポートをしてみませんか?