成果物
www.youtube.com
散歩をしていると、薄明光線を見つけたので、Processingでできないかと思って実装してみました。
仕組み
BlendModeをAddに変更したうえで、Perlinノイズで線の透明度を変化させるとこのようになります。
今回のアルゴリズムは、Wikipediaの画像を参考にして考えました。
薄明光線 - Wikipedia
www.youtube.com
散歩をしていると、薄明光線を見つけたので、Processingでできないかと思って実装してみました。
BlendModeをAddに変更したうえで、Perlinノイズで線の透明度を変化させるとこのようになります。
今回のアルゴリズムは、Wikipediaの画像を参考にして考えました。
薄明光線 - Wikipedia
線状にサンプリングする時に、自力で計算しないといけないと思って作ってみました。ただ、コンピューターで線を引くには少し工夫が必要です。今までやったことがなかったのでやってみました。
始点と終点の差計算しておき、xの位置に応じてyを計算するという仕組みです。ただ、この方法は非効率なので、別の方法も存在しています。
Line drawing algorithm - Wikipedia
前回、Perlinノイズの勾配を使ってPerlinノイズの渦を作りました。この渦には一か所に集中しないという特性があり、このことが画像変形に役立つのではないと思って作ってみました。試していくと、他のベクトル場でも画像変形出来たので、紹介していきます。
www.youtube.com
Perlinノイズをベクトルの角度としてベクトルを求め、そのベクトル場にそって画像のサンプルをとる位置をずらすとこのようになります。Perticleを使ってベクトル場の様子を観察するとわかる通り、つままれたような変形の仕方をします。
www.youtube.com
このベクトル場は一点に集中するような形になっているのが特徴です。上手くいくか不安だったのですが、このベクトル場の特性が見事に拡大、縮小の効果となって表れています。
www.youtube.com
このベクトル場は、特定の箇所に集中せず、ぐるぐると同じ軌道を回り続けるようになっているのが特徴です。画像でもねじれが見事に表れています。
画像の補完を行うために、毎度恒例となりつつあるBicubic補完を利用しています。詳しくはこちらをご覧ください。
nekodigi.hatenablog.com
画面上の位置を画像上の位置に対応させればよいので、画面上の位置から出発して、ベクトル場にそって数回に分けて移動させたあとに、map()関数を使って、画面上の位置と画像上の位置を対応させています。
Image_Perlin*という名前で追加しています。
github.com
www.youtube.com
Perlinノイズの勾配を前回作ったのですが、これを90°回せば、同じ軌道をずっと回り続けるのではないかということでやってみました。
www.youtube.com
Perlinノイズを入力として与えるので、そのままのパラメーターが使用できます。
Perlinノイズの勾配のコードなどはこちらの記事を参考にしてください。
nekodigi.hatenablog.com
今回のコードは、得られた勾配ベクトルを、そのまま90°回転させたものです。
Perlin Vortex with Gradientといいう名前で追加しています。
github.com
www.youtube.com
ProcessingでどうやってMidiファイルを扱うのかが長年の謎だったのですが、標準ライブラリを使ってMidiデータが扱えることがわかりました。再生速度などをいちいち考慮しないといけないと思っていたのですが、Sequencerを使って簡単に再生出来ることが分かったので、一旦投稿します。機能を盛り込もうかと思いましたが、既出のネタだったので、分かりやすさ重視でコンパクトに収めておきます。
今回のプログラムは、こちらのプログラムの最重要部分を抽出したものです。詳細を知りたい方はこちらをご覧ください。
github.com
まず。Sequencerを作成し、
Sequencer sequencer = MidiSystem.getSequencer();
midiFileを指定します。
sequencer.setSequence(MidiSystem.getSequence(midiFile));
Sequencerをアクセス可能にします。
sequencer.open();
どのキーが押されたか取得するために独自でReceiverを拡張したクラスを作成します。そして、Transmitterを使って、Receiverに転送します。
Receiver receiver = new myListener();
Transmitter transmitter = sequencer.getTransmitter();
transmitter.setReceiver(receiver);
あとは、再生するだけです。
sequencer.start();
曲が終わったあとは、stop() close()を行う必要があります。詳しくはコードをご覧ください。
Simple_Midi_File_Testという名前で追加しています。
github.com
Public Domainですが、一応音源のリンクを張っておきます。
Music Listing - without preview images
Peano曲線がL-Systemを使って描けることが分かったので、調べてみると非常に多くの空間充填曲線があることが分かったので実装してみました。今回は、線に色を付けることで、描画方法の特徴がわかるようにしました。単位正方形全体を含む曲線を空間充填曲線というようなのですが、今回は、隙間なく並んでいる曲線なども含めて紹介していきます。
空間充填曲線 - Wikipedia
www.youtube.com
Blenderのレンダリングでも使われている、有名な空間充填曲線です。
www.youtube.com
Hilbertが使われることが多いですが、Peano曲線も有名な空間充填曲線の一つです。
www.youtube.com
L-Systemで空間を埋める三角形のフラクタルが書けるようです。私が昔作った三角形のフラクタルとは違いますが、こちらも綺麗です。
www.youtube.com
複雑な図形ができるですが、実はタイルのように並べることが可能です。
www.youtube.com
Hilbert曲線などと同じく、正方形になりますが、かなり複雑な形状をしています。
www.youtube.com
先ほどの六角形バージョンです、回転するように成長するのが特徴です。
www.youtube.com
おまけとして、スカスカのフラクタルも紹介しておきます。こちらのフラクタルも色々なところで使われています。
L-Systemのルールを以下のように変更すると、空間充填曲線を描くことができます。線の長さは、それぞれ違った調整を行わなければなりません。どんな数で割ればいいのか、generate(x)というように例を示しておきますが、詳しくはソースコードを参照してください。
L-Systemのルールはこちらのサイトを参考にしています。
L-System manual
axiom = X
X -> -YF+XFX+FY-
Y -> +XF-YFY-FX+
angle = 90
generate(1);
generate((1.*2+1)/1);
generate((3.*2+1)/3);
axiom = X
X -> XFYFX+F+YFXFY-F-XFYFX
Y -> YFXFY-F-XFYFX+F+YFXFY
angle = 90
generate(2);
generate((2*3+2)/2.);
generate((8*3+2)/8.);
axiom = F+F+F
F -> F-F+F
angle = 120
generate(1);
generate(1.7);(不明)
axiom = FX
X -> X+YF+
Y -> -FX-Y
angle = 90
generate(1);
generate(1.43);(不明)
axiom = -YF
X -> XFX-YF-YF+FX+FX-YF-YFFX+YF+FXFXYF-FX+YF+FXFX+YF-FXYF-YF-FX+FX+YFYF-
Y -> +FXFX-YF-YF+FX+FXYF+FX-YFYF-FX-YF+FXYFYF-FX-YFFX+FX+YF-YF-FX+FX+YFY
angle = 90
generate(5);
generate(5);
axiom = XF
X -> X+YF++YF-FX--FXFX-YF+
Y -> -FX+YFYF++YF+FX--FX-Y
angle = 60
generate(2.8);
generate(2.8);(不明)
axiom = F
F -> -F++F-
angle = 45
generate(1.43);
generate(1.43);(不明)
L-System*という名前で追加しています。
github.com
どうして分光できるのかと思って調べてみたら、波長によって屈折率が変わるということがわかりました。狙った波長のデータが見つからなかったので、残念ながら物理的に正確なシュミレーションは出来ませんでしたが、近い見た目のものができました。
波長によって屈折率が変わるということを再現するために、光線自体に屈折率情報を持たせておき、それを使ってスネルの法則で屈折の計算を行っています。
Snell's law - Wikipedia
狙った波長ではなかったので今回は使いませんでしたが、屈折率と波長の関係のデータはこちらから取得することができます。
https://www.global-optosigma.com/jp/category/opt_d/opt_d01.html
RayCast_Prismという名前で追加しています。
github.com
www.youtube.com
今回はフィボナッチ数列の辺の長さの正方形を敷き詰め、円弧でつなげてみました。
フィボナッチ数列は、1,1,2,3,5,8,13,21というようになっている数列です。どう並べるか悩んだのですが、素直に動かす方向ごとに、処理を変えることで対応しています。
Fibonacci number - Wikipedia
Fibonacci Numberという名前で追加しています。
GitHub - Nekodigi/Math: Time estimate and more
Sobel Operatorを実行すると、この様に輪郭が検出できます。予め決まった行列を掛け合わせるだけのシンプルな仕組みです。
水平方向と垂直方向の輪郭に反応する行列を畳み込み演算し、それぞれの結果を二乗して足し合わせ平方根を求めると、Sobel Operatorが実現できます。
数式等が貼り付けられなかったので、こちらのサイトを参照してください。
Sobel operator - Wikipedia
【画像処理】ソーベルフィルタの原理・特徴・計算式 | 西住工房
Image Sobel Filterという名前で追加しています。
github.com
ある点からの距離結果が変わるように拡張したガウス関数を使ってフィルタになる行列を作ります。そのフィルタを使って、全ピクセルにフィルタをかけるとGaussian Blurを行うことができます。境界の処理ではConstrain関数を使って有効範囲に制限しています。
ガウシアンぼかし - Wikipedia
Image Gaussian Blurという名前で追加しています。
github.com
www.youtube.com
橋を作るゲームを見て、壊れる動作が、どうやったら再現できるのか気になったので、破壊可能なばねを作ってみました。
物体が壊れるのは力がかかった時というイメージがありますが、力を計算するのは難しいです。ただ、物体は力がかかった時伸び縮みするので、伸び縮みを観測し、それをもとに物体を破壊すれば力を計算しなくて済むという仕組みになっています。
Destructible Springという名前で追加しています。
github.com
www.youtube.com
アイヨシキさんに、視覚化したらきれいな数学の問題はありますかと聞いたらビュンフォンの針を紹介していただいたので、さっそく実装してみました。ただ、精度が悪いのが難点です。
感覚dの平行線を書き、長さがd/2の針を落とすと、平行線と交差する確率がになります。針を落とす動作は、平行線内のランダムな位置に、ランダムな角度で置くことで実現できます。
mathtrain.jp
Buffons Needleという名前で追加しています。
github.com
www.youtube.com
アイヨシキさんがTaylor展開を作ろうとしていたのを見て、お蔵入りになっていたマクローリン展開を思い出しました。お蔵入りになっていたマクローリン展開をちょっと改良すればTaylor展開を作れるのでは、ということで作ってみることにしました。
Taylor series Formulaという名前で追加しています。
github.com
www.youtube.com
HoudiniでRelaxノードというものを使って、Differential Growthを実装するTutorialを見たのですが、Processingでも簡単に出来そうなのに一度も実装したことがなかったので、さっそく実装してみました。
Relaxは頂点をある大きさの円だと見なして、ぶつからないように移動させるというものです。
Relaxを行い、点と点の距離が一定になるようにResampleし、繰り返すとDifferential Growthが出来ます。Relaxノードはぶつかった円の法線方向にずらすだけでいいのですが。Resampleがなかなか大変でした。等間隔にサンプリングしていくと、最後に少し余りが発生してしまいます。このままだと、毎回終点の周りがスカスカになってしまいます。そこで、始めからと終わりから交互にResampleするとうまくいくはずです。ですが、普通のResampleをちょっと工夫をするとうまく動いてしまいまったので、そちらを採用しました。
今回は辺にSmoothをかけていないせいか、点が交差し始め発散してしまったので、Resampleをした時に離れすぎ内容に調整する処理を挟みました。
Line Differential Growthという名前で追加しています。
github.com
www.youtube.com
パーリンノイズを累算して何かアニメーションが作れないかなと思っていたら、Houdini TutorialでAgate Sectionというものが紹介されていたので、自分もアゲートを作ってみました。
パーリンノイズを円状にサンプリングして、記録しておきます。その後、記録したデータを足し合わせ最終的なアゲートの半径を求めます。ただ、足し合わせながら表示すると大きい層に隠されるので、先に合計を求めてから引き算しています。
今回は見栄えのために周りを薄くしています。このサイトを見たところ、Agateは外側から成長するようなので、うまくいったらまた試してみたいです。
stonebuyer.exblog.jp