So-net無料ブログ作成

自作の " HTML5 インタラクティヴ アート " の説明。 [HTML5 インタラクティヴ アートの説明]

私が遊びで作成した " HTML5 インタラクティヴ ジェネレーティヴ ディジタル アート " について説明致します。
JS_Art_SS_(2017_05_23)_2_Cropped_1 HTML5 インタラクティヴ ジェネレーティヴ ディジタル アートのスクリーンショット画像。 黒い背景の上に1つの光の円盤がある。 光の円盤からは 眩しく光り輝く青緑色の粒子が多数放出されており、青緑色や青紫色のリボンのような曲線が多数くねりながら放射されている。 光の円盤の周囲には青緑色の光輪がある。
https://c1.staticflickr.com/5/4272/34845047985_98d357231a_o.png
これは自作のHTML5 インタラクティヴ ジェネレーティヴ ディジタル アートのCanvas上をクリックして多数の粒子を放出させ、音を出した瞬間のスクリーンショット画像です。

このプログラムでは " Canvas Play / Stop " ボタンを押してからCanvasをクリックする事によって、正弦波の音や弦を弾く音の出力をしたり、模様や粒子を描画したり、キーボードのキーを押してピアノのような演奏をする事が出来ます。
特に重低音の迫力のある再生に拘っており、大型のサブウーファーなどで再生すると強力な重低音を楽しめます。
また、音楽ファイルを再生させ、スペクトラム アナライザーのヴィジュアライザーを表示させる事も出来ます。

プログラムのコードはGoogleが提供しているJavaScript ソースコード圧縮サーヴィスである " Closure Compiler " にて、 " Simple " モードよりも強力な圧縮、最適化オプションである " Advanced " モードで圧縮したものを下記のブログ記事のHTML ページ内にインライン JavaScriptで埋め込みました。
プログラムのコードは文字数が多い為、圧縮せずに記事内に埋め込んでブログの投稿ボタンを押すと " 記事本文は100,000文字以内でご入力ください。 " と表示されてしまい、投稿出来ません。

HTML5のCamvasと "JavaScript" で音声処理と画像描画。
http://crater.blog.so-net.ne.jp/2016-06-30

HTML5Canvas要素Web Audio APIのみを利用しており、JavaScriptで記述しております。
外部のライブラリーなどは使用しておりません。
古いウェブ ブラウザーでは動作しませんが、PC用の新しいウェブ ブラウザーならば動作する筈です。

尚、私のプログラミング スキルは入門者以下のレヴェルですので、間違いが多いかと思いますが御容赦下さいませ。

因みに当該プログラムのソースコードは御自由に切り貼りして利用して下さって結構です。

" Yahoo!ボックス " サーヴィスにソース コードのhtml ファイルをアップロードして公開させて頂きます。
次のリンク先のページにある " ダウンロード " ボタンを押すと当プログラムのhtml ファイルをダウンロード出来ます。

[ソース コード]
Yahoo!ボックス: http://yahoo.jp/box/d0j0Ki



" Closure Compiler " でコードを圧縮するに当たっては、プログラムのコンストラクターがコンストラクターである事を認識させる為に、JsDoc タグのアノテーションによる型定義でそれがコンストラクターである事を明示する必要がありました。
それをしないと " Warning " (警告)が出てしまいました。

次のアノテーション(注釈)を全てのコンストラクターの定義部分の1行上に加えました。
/** @constructor */ 


他には、 " Closure Compiler " が私の記述の僅かな誤りなどを指摘してくれるので、1箇所づつ修正して行きました。

しかし、圧縮後にローカル ファイルとしては問題無く動作していたコードが、ブログ記事内では一部の動作に異常が生じて正常な表示が出来なくなる問題がございました。
私が非常にありがたく利用させて頂いている " i2i " アクセス解析サーヴィス有料版の埋め込みコードによってPHP ファイルが読み込まれるようで、これを見ると、グローバル変数として " C " という文字が使用されておりました。
実は、 " Closure Compiler " がコードを高度に圧縮した結果、変数名はアルファベット1文字、2文字程度に短縮され、私がグローバル変数としていた変数名が " C " となった為、外部ファイルのグローバル変数と名前が重複してしまい、衝突が起きていたのでした。

そこで、自作のプログラム全体を1つのコンストラクターに収め、グローバル変数をそのコンストラクターのスコープ内のローカル変数とする事により解決致しました。
<script type = "text/javascript">
/** @constructor */
var globalObjectOfThisProgram = function()
{
 ...
 ...
}
new globalObjectOfThisProgram();
</script>

この様に記述する事によりブログ記事内へ埋め込んでも正常に動作するようになりました。

ソース コードが埋め込まれたHTML ファイルのサイズは、圧縮前の323.8[kB]から、76.5[kB]へと激減致しました。

[Closure Compilerに関して私が参照したウェブサイト]
"@wiki" のウィキ サイト "Closure Compilerを使う!" のページ "Compilerが求めるコーディングルール" のURL:
https://www37.atwiki.jp/aias-closurecompiler/pages/20.html

"@wiki" のウィキ サイト "Closure Compilerを使う!" のページ "アノテーションによる型定義" のURL:
https://www37.atwiki.jp/aias-closurecompiler/pages/22.html

"Qiita" のページ "Closure Compiler の ADVANCED_OPTIMIZATIONS の使い方" のURL:
http://qiita.com/senda-akiha/items/82f670a78ff592c054ab

"modest" のページ "JavaScript のブロックスコープと名前空間" のURL:
https://dev.mozilla.jp/2010/05/js-blockscope-and-namespace/



プログラムの実行速度を向上させる為に、ループ ブロック内では定数同士の計算を行わず、ループに入る前に予め計算を済ませて置くといった事を徹底しております。
また、本プログラム中の多くのアニメーション描画では、個別の描画対象毎に " setInterval(); " で定期的に描画関数を呼び出し、 " clearInterval(); " で描画を停止させる処理を行っております。



JS_Art_SS_(2017_05_23)_2_Cropped_1 HTML5インタラクティヴ ジェネレーティヴ ディジタル アートのスクリーンショット画像。 黒い背景の上に1つの光の円盤がある。 光の円盤からは 眩しく光り輝く青緑色の粒子が多数放出されており、青緑色や青紫色のリボンのような曲線が多数くねりながら放射されている。 光の円盤の周囲には青緑色の光輪がある。
このプログラムではCanvasをクリックした際にその点を中心に放射状に曲がりくねったリボンの様な曲線が描画されます。
この曲線はベジェ曲線であり、その曲線の制御点はある範囲内に偏り無く位置するようにし、逆にその曲線の末端の点の座標はクリックした点の付近に位置する確率を高くする事によって、より多く曲がりくねった曲線にしております。
乱数を2回生成して足し合わせ、それを2で除して相加平均を求めると、値の出現確率分布は中央値が最多で両端が最小の三角形を描きます。
乱数を3回以上生成して足し合わせ、それを生成回数で除して相加平均を求めると、値の出現確率分布は中央値が最多で両端が最小の釣り鐘形を描きますので、値の範囲の中央がクリックした点の座標になるように処理すれば、曲線の末端がクリックした点の付近に位置する確率を高くする事が出来る訳です。




JS_Art_SS_(2017_06_12)_1_Cropped_1 HTML5インタラクティヴ ジェネレーティヴ ディジタル アートのスクリーンショット画像。 黒い背景の上に1つの光の円盤がある。 光の円盤からは 眩しく光り輝く青色の粒子が多数放出されている。 光の円盤の周囲には青色の光輪がある。 画面の下方には音楽のスペクトラム アナライザーのヴィジュアライザーが描画されており、垂直の青色のバーが多数横方向に並んで伸び縮みしている。 青色のバーは明るさと再度と色相に微妙なグラデーションが掛かっている。
https://c1.staticflickr.com/5/4235/34423804153_be239c1372_o.png
ファイルを選択する為のボタンを押し、自身の端末に保存されている音楽ファイルを複数選択してから " Music Play / Stop " ボタンを押すと音楽を再生出来ます。
この際、音楽ファイルへのリンクショートカットエイリアスを選択する事も可能ですので、プレイリストのように利用可能です。
1曲分の再生が終わると次の曲が自動的に再生されます。
また、読み込んだ音楽ファイルのリストから別の曲を選択すると、別の曲に切り替わります。
音楽ファイルを再生させながら、自身でキーボード演奏して音を重ねる事が可能です。
至高の重低音プレイを楽しみたい場合は、このウェブ プログラムで重低音の似合う楽曲を再生させながら、キーボード演奏機能オクターヴ番号のラジオ ボタンで " 1 " を選択して、キーボードの下段と上段を弾くと凄い体験が出来ます。
Canvas画面にはスペクトラム アナライザーヴィジュアライザーが表示されます。
スペクトラム アナライザーは " AudioBufferSourceNode " -> " GainNode " -> " ChannelSplitterNode " -> " AnalyserNode " -> " ChannelMergerNode " -> " audioContext.destination " の流れで接続しております。
これにより、ステレオの左右チャンネルが別々にスペクトラム表示出来ます。
周波数帯域毎に、配列に現在の値を保存して置き、現在の値と前回値との差が正の値であれば積算用の配列に加算して行きます。
積算用の配列の値は一定時間毎に一定の割合で減少して行くようにしてあります。
これにより、周波数帯域毎に時間軸上に於けるレヴェルの変化が急峻である時にスペクトラムのバーを光らせ、色を変化させる事が出来ます。
音楽再生の音量はスライダーで調整可能にしてあります。
音楽の再生の音量とスペクトラム ヴィジュアライザーのバーの長さは、原点座標が(1,1)で(0,0)を通る3次関数により対応させておりますので、ある程度ヴォリュームを下げてもヴィジュアライザーは適切な高さで表示されます。
音楽ファイルの読み込みはHTML5の " input " 要素で " type="file" " 、 " multiple " 属性を付けたボタンによりファイルを選択出来るようにし、 " window.URL.createObjectURL( fileList[i] ) " でファイル毎のURLを生成させ、音楽再生時に " XMLHttpRequest " でURLからデータを取得し、 " audioContext.decodeAudioData() " で音楽データをデコードして、バッファーにデータを入れて出力させます。
オーディオの再生が終わると発行される、 " AudioBufferSourceNode " の " onended " イヴェント ハンドラーのコールバック関数で曲の切り替えやリピートを制御しております。
因みに、スペクトラムのバーの描画では、 " canvasContext.beginPath(); " -> " canvasContext.moveTo( x, canvasContext.canvas.height - y ); " -> " canvasContext.lineTo( x, canvasContext.canvas.height ); " -> " canvasContextLayer.stroke(); " で描画するのと比べ、 " canvasContext.fillRect( x - lineWidth / 2, canvasContext.canvas.height - y, lineWidth, canvasContext.canvas.height ); " で描画した方が2.8倍高速でした。



次に、音の生成に関して説明致します。
音の生成に於いては、Oscillator ノードを利用する方法ではノイズが出たのでこれは使用せず、計算で波形を生成させております。

私の環境では突然に音を出力させるとノイズが出るので、 " Canvas Play / Stop " ボタンを押してからもう一度押すまでの間、極微小音出力をする事でノイズを軽減しております。


ラジオ ボタンのオプションで " Sine Wave " を選択してCanvas上をクリックすると、計算により正弦波形を生成して音を出力致します。
この正弦波形はAttack, Decay, Sustain, Releaseに分けて処理しております。
Attack部分とDecay部分の包絡線(エンヴェロープ)はそれ自体が正弦波形にしてあり、音量変化が滑らかに推移致します。
Release部分の包絡線は直線的に減衰し、最後には無音になります。
加えて、Attack部分は周波数変調(FM)で基本の周波数よりも高い周波数からの導入とする事で低音域のアタック感を増強してあります。
この時には、シグモイド関数によって音の中心周波数の高さとAttack部分の周波数変調の最大周波数の高さとを対応させ、低音域にだけ周波数変調が効くようにしております。
Release部分に於いては三角関数の式の中の時間を徐々に遅らせる事によって位相を遅らせ、時間と共により低周波数の方へと遷移させる処理を、2つのシグモイド関数の和を取って係数にして重み付けをする事により低周波数領域に限って適用させております。
余韻の長さにつきましては、クリックする位置がCanvasの左側に行く程余韻が短く、右側に行く程余韻が長くなります。
この時には、シグモイド関数によって水平方向の位置座標と余韻の長さとを対応させております。
また、クリックする位置が上側に行く程に高音が出力され、下側に行く程に低音が出力されます。
この時には、3つのシグモイド関数の組み合わせにより、垂直方向の位置座標と音高とを対応させております。

出音の持続に関しまして、マウスのボタンを押している時間だけSustainの部分をリピート機能により繰り返す事で出音を持続させる事が出来ます。
マウスのボタンを放すとRelease部分へ遷移して出力は次第に小さくなり、最終的には無音となります。
持続する音の出力を正常に終了出来なくなったりする事を防ぐ為に、イヴェントの状態監視、管理を徹底致しました。
キーのコードを文字列で持つオブジェクトを作成、利用し、キーボードのキーやマウスのボタンの状態を格納して参照し、同時に各キー毎にAudioBufferSourceNodeを格納して管理致します。
キーボードのキーを押しながらブラウザーのタブを切り替えた場合なども考慮して処理を行います。
また、Sustain部分の波形からリピート部分を正確に切り出さないとノイズが発生したり音程が変化してしまいます。
周波数変調により位相が変化しているので、リピート部分の切り出しに際してその位相変化分を考慮する必要がございます。
そして周波数の逆数である周期を求め、Sustain部分の長さ目一杯に、かつ半端な部分が生じないように、1周期の整数倍で切り出すように致しました。
また、高音域程ループ切り出しの際にサンプリング精度が不足するので、この事により意図せずに音程が変化してしまったり雑音が発生してしまったりする事を防ぐ為に、正弦波出力の場合はサンプリング周波数をオーディオ デヴァイスのサンプリング周波数4倍にして波形データを生成する事により時間軸上での切り取り位置の誤差を低減致しました。
出力時はこれを4倍の早送りで再生する事で音程を調整しております。

因みにGoogle Closure CompilerのAdvanced モードで正しく変換出来るようにする為、キーの管理の為のオブジェクトのプロパティへのアクセスをドット表記ではなくブラケット表記で統一する必要がございました。
正弦波音の出力の音量に関しまして、高音域程人間の耳には刺激的で不快に感じる事から、シグモイド関数により、低音域と比較して高音域の音量を下げるように致しました。


ラジオ ボタンのオプションで " Triangle Wave " を選択してCanvas上をクリックすると、計算により三角波形を生成して音を出力致します。
この三角波形も正弦波の場合と似たような処理となっております。
正弦波の場合との主な違いは波形の生成方法です。
こちらの波形の生成は三角関数によるものではなく、数値の " 1 " と " - 1 " とを閾値として、その閾値に達するまで一定の値を加算して行き、閾値に達したら加算する値の符号を反転させるという処理を繰り返す事により波形を生成致します。
加算する値を増減する事により、周波数を変化させております。


ラジオ ボタンのオプションで " Click or tap the canvas. " を選択している時は、マウスによるクリックまたはタッチ操作対応デヴァイスでのタッチによってのみ正弦波及び三角波の音の出力が可能です。
ラジオ ボタンの選択状態を一時的に固定した上で選択不可状態にしたり、選択不可状態を解除したりする機能を実装致しました。
内容としては、 " document.getElementsByName( 'radioButton' ).checked = true " としたり、ラジオ ボタンの属性に " .disabled = true " を付加したり、 " .disabled = false " にしたりしております。
このモードでは追加の視覚効果の描画機能をどれでも働かせる事が出来ます。


ラジオ ボタンのオプションで " Input from the keyboard. (Let's play the keyboard!) " を選択している時は、マウスによるクリックまたはタッチ操作対応デヴァイスでのタッチに加えて、 " QWERTY " 配列の一般的な文字入力用キーボードのキーを押す事によってピアノのようなキーボード演奏が可能です。
このモードでは追加の視覚効果の描画機能は " Particles Emission " のみ働かせる事が出来ます。
音域をオクターヴ ナンバーのラジオ ボタンで選択する事が可能で、第0オクターヴから第9オクターブまで選択出来ます。
キーボードの " Shift キー " を押下しながら発音用のキーを押すと、キーボードの下段ではオクターヴを1つ下げた音となり、キーボードの上段ではオクターヴを1つ上げた音となります。
複数のキーを同時に押すと " 和音 " も出せます。
音名とキーとの対応は次の通りです。
[選択されたオクターヴ ナンバーの音]
(z):c (s):cs (x):d (d):ds (c):e (v):f (g):fs (b):g (h):gs (n):a (j):as (m):b (,):c
(Shift): 1 オクターヴ下がります。

[選択されたオクターヴ ナンバーの1つ上のオクターヴの音]
(q):c (2):cs (w):d (3):ds (e):e (r):f (5):fs (t):g (6):gs (y):a (7):as (u):b (i):c
(Shift): 1 オクターヴ上がります。

このモードでキーボードのキーの押下を検出する為にイヴェント リスナーを追加致しました。
そしてキー押下イヴェントを処理する関数内で、 " switch文 " でキー コード毎に " case " で場合分けして出音の処理を行っております。

音は音名でC0からB9までを440[Hz]A4の音を基準音として、音名と周波数の値との対応関係を配列とオブジェクトの組み合わせで管理致しております。
このモードでもキーボードのキーを押している時間だけSustainの部分をリピート機能により繰り返す事で持続させる事が出来ます。
キーを放すとRelease部分へ遷移して出力は次第に小さくなり、最終的に無音となります。

第1オクターヴという重低音域で弾く " Für Elise / Ludwig van Beethoven " (エリーゼのために / ベートーヴェン)も面白いです。

ところで、オクターヴ0やオクターヴ1の音を再生出来るかどうかで、そのオーディオの低域再生能力の限界が分かります。
ヘッドフォンやイヤフォンではなく、スピーカー システムを御使用の場合、大型のサブウーファーが無いと、おそらく最低域は再生出来ない事でしょう。


ラジオ ボタンのオプションで " Auto rhythm playback. " を選択している時は、ランダムに呼び出される異なる短いリズムの音が自動的に再生されます。
このモードでは追加の視覚効果の描画機能は " Particles Emission " のみ働かせる事が出来ます。
このモードでも音域をオクターヴ ナンバーのラジオ ボタンで選択する事が可能です。
マウスによるクリックまたはタッチ操作対応デヴァイスでのタッチでの発音も可能です。
キーボード演奏モードの時と同様の、音名と周波数の値との対応関係を配列とオブジェクトの組み合わせを用いて、インターヴァル タイマーで波形生成関数を呼び出して演奏させております。


ラジオ ボタンのオプションで " Random Sound. " を選択している時は、ランダムな音ランダムなタイミング自動的に再生されます。
特に凝った事は何もしておりません。
このモードでは追加の視覚効果の描画機能は " Particles Emission " のみ働かせる事が出来ます。
マウスによるクリックまたはタッチ操作対応デヴァイスでのタッチでの発音も可能です。


ラジオ ボタンのオプションで " Guitar " を選択すると、ギターの弦の振動をリアルタイムで物理シミュレーションして音を出す事も出来ます。
このシミュレーション コードの原型は現在、岡山大学理学部で准教授をなさっている方が昔にウェブサイトで公開して下さったもので、パブリック ドメインとして良いとの事ですので、これを私がJavaScriptで書き換え、加工し、プログラムに組み込みました。
尚、シミュレーションは弦の部分のみで胴の響きはシミュレーションしていない為、本物のギターとは少々違う音色となっております。
e-メールでコードの使用を快諾して下さいました事に感謝申し上げます。

尚、ギターの物理シミュレーション音源については、計算量が非常に多い為、性能が低目のCPUではCanvas上をクリックしてから発音までに時間差があるようです。高速なCPUでは遅延は極僅かしかございません。

因みにラジオ ボタンのオプションで " Guitar (with the visualization of the vibration of the string.) " を選択するとギターの弦の振動の様子を描画致します。

JS_Art_SS_(2017_05_25)_3_Cropped_1 HTML5インタラクティヴ ジェネレーティヴ ディジタル アートのスクリーンショット画像。 黒い背景の上に1つの光の円盤がある。 光の円盤からは 眩しく光り輝く青緑色の粒子が多数放出されされる寸前の状態であり、青色や紫色のリボンのような曲線が多数くねりながら放射されている。 光の円盤の周囲には青緑色の光輪がある。 画面中央には色とりどりの細い紐が数多く半時計回りに傾いた平行四辺形状にやや波打ちながら描かれている。
https://c1.staticflickr.com/5/4272/34834024266_c72322bc5d_o.png

以下、ギターの弦の振動シミュレーションの計算方法を説明致します。

計算速度を重視し、簡略化したシミュレーションです。

仮想的な弦に100個程の質点を設定し、質点同士をバネで繋いだ構造と致します。
バネにはバネ係数が設定されており、周波数を変える機能はこのバネ係数を変える事により実現しております。

まず、(f: 質点に加わる力, m: 質点の質量, a: 質点の加速度, v: 速度, z: 振動方向の位置, Dt: 短い時間)と致します。
運動方程式 " f = m * a " と致します。

質点に加わる力fは各質点の両隣の質点との位置zの差に比例するものと致します。

振動を時間と共に減衰させる為に、質点の速度に比例した摩擦係数を設定致します。

初期値として弦をピッキングする位置である弦の端から1 / 4の位置にある質点を大きく変位させ、弦の端の変位を常に0に固定した上で各質点を弦全体がピッキング位置と両端を頂点とする三角形になるように設定しておきます。

後は " a = f / m " で加速度aを出し、その瞬間の速度vを " v = a * Dt " として求めます。

最後に質点の位置zを " z = z + (v * Dt) " として求めます。
これを各質点全てに対して順次行います。

そしてピッキング位置に近い方の末端の1つ手前の質点の振幅の2乗をバッファーに格納致します。

この状態から " サンプリング周波数 * 発音時間 " だけ同様に繰り返し計算します。
計算が終わったらステレオにする為にチャンネルを複製致します。

但し、これには膨大な量の計算が必要になり、基本的にはシングル スレッド処理であるJavaScriptでは計算が終わるまで他の処理が停止してしまい、画像の描画なども停止し、更にはブラウザーからスクリプトを停止するかと尋ねるダイアログ ウィンドウを出されてしまいます。

そこで、繰り返しの計算処理を一定の回数毎に分割し、 " setTimeout() " 関数に続きの処理を行う関数を引数として渡して処理の再開を予約した上で一旦関数を終了させる処理に致しました。

こうする事で溜まっていた別の処理のキューが実行され、その後に元の繰り返し計算の関数が " setTimeout() " 関数から呼ばれ、処理が再開されるのです。

但し、変数のスコープを意識しておかないと、再開後に変数の参照が切れてしまい、正しく計算できなくなってしまうので、この点は注意が必要です。
こうして画像の描画など他の処理を停止させる事無く膨大な量の計算をシングル スレッドであたかもマルチ スレッド処理であるかの様に実行出来るように致しました。



以下に視覚効果の説明を致します。

オプションの " Simplify. " のチェックボックスチェック マークが入っていると、曲がりくねるリボンの様な模様は描画されません。


" Particles Emission " を選択すると、Canvas上をクリックして音が出るのと同時に光の輪が広がり、クリックした位置から色の着いた多数の光る粒子が散り散りに飛んで行きます。
それらの粒子にはグロー効果によって光り輝いて見えるようにしてあります。
個々の粒子はx軸方向、y軸方向にそれぞれランダムに加速、減速する事により軌跡が湾曲致します。

JS_Art_SS_(2017_05_23)_2_Cropped_1 HTML5インタラクティヴ ジェネレーティヴ ディジタル アートのスクリーンショット画像。 黒い背景の上に1つの光の円盤がある。 光の円盤からは 眩しく光り輝く青緑色の粒子が多数放出されており、青緑色や青紫色のリボンのような曲線が多数くねりながら放射されている。 光の円盤の周囲には青緑色の光輪がある。
これはJavaScript プログラムによる自作のインタラクティヴ ディジタル アートで画面上をクリックして多数の粒子を放出させた瞬間のスクリーンショット画像です。

HTML5のCanvasの基本的なAPI円形グラデーション描画機能が用意されていましたので、これを利用致しました。
ところが、数百個のパーティクルのアニメーションを毎回円形グラデーション処理で描画するとさすがに処理が重過ぎて動作が鈍くなってしまいました。
ですので、Canvas Contextをレイヤーとして利用する事とし、これを配列で多数用意し、そこにCanvasをクリックした時のアニメーションの最初に円形グラデーション機能で粒子を描画し、その後のアニメーション描画時にその画像を位置と縮尺を変えて複写する事により、毎回円形グラデーション機能で描画するよりも高速な描画を実現致しました。


" Wavelet of Tiled Dots " を選択してCanvas上をクリックすると、多数の丸いドット模様タイル状に並び、クリックした位置から波紋が広がるかのようにドットの大きさと色の濃さの変化が連続的に周囲に伝わり、波打ちます。

JS_Art_SS_(2017_05_24)_1_Cropped_1 HTML5インタラクティヴ ジェネレーティヴ ディジタル アートのスクリーンショット画像。 画面全体に小さな円盤状のドットがタイル状に並び、ドットの色が左上から右下に掛けて橙色から黄色、青緑色までのグラデーションとなっている。 画面中央に白い光の円盤があり、そこを中心としてドット模様が濃淡とドットの円盤の大きさの大小により波打ち、円弧状に波紋が広がっている様に見える。
https://c1.staticflickr.com/5/4225/34029175334_b3839595ce_o.png
これは波打つドット模様のスクリーンショット画像です。

2次元メッシュの交点に質点を配置し、各質点をバネで結合し、各辺は自由端としてあります。
自由端反射の様子も見られます。
自由端ですので、そのままでは振動させると面全体が糸が切れた凧の様に飛んで行ってしまいますから、これを防ぐ為に各質点とゼロ水準の基準面とをバネで繋いであります。
質点の変位の大きさを丸の大きさと彩度の変化で表現して描画しております。
計算式は前述のギターの弦の振動のシミュレーションの応用です。

実はこのバネの2次元メッシュは4辺を固定端にして面の各質点の変位の平均値をとって時間毎に記録して行くと打楽器のティンパニーの様な音を発する事が出来たのですが、計算量がとても多く、ハイエンドのCPUを搭載したPCでないと実時間ではシミュレーション出来ないものでした。
私のPCではこれを行おうとすると音が出るまでに数秒間待たされました。


" A Large Amount of Particles " を選択してCanvas上をクリックすると、大量の粒子の物理シミュレーションが出来ます。
大量の粒子と画面のポインターとの間の引力と斥力の相互作用を計算しており、3次元空間大量の粒子を引力でポインターに引き付けて操る事が出来ます。
また、クリックすると粒子を撥ね退ける事が出来ます。
また、重力が働いており、ポインターの引力圏から離れた粒子は床に落ちて行きます。
想像力により、銀河の運動などの宇宙を感じたり、磁場によって砂鉄が引き寄せられる現象に見立てたり、原子などのミクロな世界を想像したりする事も出来ることでしょう。

JS_Art_SS_(2017_05_24)_2_Cropped_1 HTML5インタラクティヴ ジェネレーティヴ ディジタル アートのスクリーンショット画像。 黒い背景の上に大量の色とりどりの粒子が散らばりつつも、それらの粒子集団は点々と連なる白い光の軌跡に纏わりついているように見える。
https://c1.staticflickr.com/5/4245/34832713336_91d6fa9af6_o.png
これは大量の粒子の物理シミュレーションをしている様子のスクリーンショット画像です。


" Precipitating Particles " を選択してCanvas上をクリックすると、3種類の質量の異なる大量の粒子水中で重力によって徐々に沈殿または浮上する様子の物理シミュレーションが出来ます。
これは2次元座標空間上でのシミュレーションです。
各粒子間の引力と斥力による相互作用、及び粒子と画面のポインターとの間の引力と斥力の相互作用を計算しております。
粒子同士の反発を計算する事により、粒子の堆積のシミュレーションを実現しております。
Canvas上をクリックすると重力の向きが上下反転致します。

JS_Art_SS_(2017_05_23)_3_Cropped_1 HTML5インタラクティヴ ジェネレーティヴ ディジタル アートのスクリーンショット画像。 黒い背景の上で赤色と緑色と青色の多数の粒子があるものは上辺に堆積し、またあるものは画面中央付近にある白色の光に吸い寄せられている様子である。
https://c1.staticflickr.com/5/4252/34832713466_540ea5a4f0_o.png
これは沈殿する粒子の物理シミュレーション機能で重力の向きを反転した状態のスクリーンショット画像です。
画面のポインターが及ぼす引力で粒子が引き付けられております。

粒子は種類毎に異なった比重としてある為、沈降及び浮上の際の速度が異なります。
各粒子とそれ以外の大量にある全ての粒子との相互作用を計算する事は負荷が高過ぎるので、工夫を施しました。
まず、画面に表示するCanvasを細かく分割した仮想の格子を配列で作成します。
次に、粒子の位置について計算の為の座標系から画面座標系へ変換した後、粒子がその格子上のどの領域にあるのかを計算し、仮想の格子に相当する配列に粒子の番号と計算の為の座標系に於ける位置情報を登録して行きます
そして粒子の次の移動の際にその粒子が属する格子の近傍の格子の領域既に登録されている粒子が在るか無いかを調べます。
近傍に粒子が無い場合には相互作用の計算は行わず、近傍に粒子が在った場合にだけ検出された全ての粒子について相互作用を計算致します。
この様な処理方法とする事で、計算量を大幅に低減出来ました。


" Moving Particles " を選択してCanvas上をクリックすると、仮想の希ガス原子の集団の運動の物理シミュレーションが出来ます。
3次元座標空間上で " Lennard-Jones ポテンシャル " の勾配によって生じる力を元に運動をシミュレーションします。
移動量の計算には " Verletのアルゴリズム " を使用しております。
この部分のプログラムのコードの原型は " 早稲田大学 渡邉研究室 " の次のページに掲載されていたC言語によるコードです。これを基に私がJavaScriptで書き換え、加工し、自作のプログラムに組み込みました。

"早稲田大学 渡邉研究室" / "Lennard-Jonesポテンシャルを用いたMDシミュレーション" のページのURL:
http://www.watanabe.nano.waseda.ac.jp/blog/archives/2107

e-メールにてコードの使用を快諾して下さいました、早稲田大学理工学術院教授 渡邉 孝信 様に感謝申し上げます。

JS_Art_SS_(2017_05_24)_3_Cropped_1 HTML5インタラクティヴ ジェネレーティヴ ディジタル アートのスクリーンショット画像。 黒い背景の上で色とりどりの多数の粒子が散らばっている様子である。 奥にある粒子はやや小さく、手前にある粒子はやや大きく描かれている。
https://c1.staticflickr.com/5/4196/34486082250_5ac19486c5_o.png
これは相互作用する仮想の希ガス原子の集団の物理シミュレーションの様子のスクリーンショット画像です。

各粒子の位置の計算後の粒子集団の描画は、初めに各粒子の位置情報を格納した配列を複製してから " Z ソート " で奥から順に並べ替えます。
そして並べ替えた順番で、 " context.createRadialGradient() " と " radialGradient.addColorStop() " を使用して円形に色のグラデーションを描画する事により球体の様な見た目を再現致しております。

この原子集団は領域外との境界面に接触すると減速し、徐々に動きが少なくなります。
そしてCanvas上をクリックすると原子の運動が活性化し、再び激しく動き出します。


" Cloth Fluctuation " を選択してCanvas上をクリックすると、色とりどりの揺らめく布を描画致します。
まず、一様なノイズスケールを変えながら三次エルミート スプライン補間法(Cubic Hermite Spline Interpolation)により滑らかに補間しつつ加算合成して行く事でピンク ノイズ データを生成致しました。
このピンク ノイズ データを三角関数で基準点からの(x, y)座標のずれにして、同じく時間軸方向にもノイズを三次補間したデータを用いて移動させつつ描画致します。

JS_Art_SS_(2017_05_24)_4_Cropped_1 HTML5インタラクティヴ ジェネレーティヴ ディジタル アートのスクリーンショット画像。 暗い背景の上で色とりどりの横長の布のような物が右から左へ向かって、はためきながらたなびいている様子である。 瓦葺きのように一部が重なり合っている。
https://c1.staticflickr.com/5/4204/34061807513_f20e7fbb77_o.png
これは色とりどりの多数の布が、揺らめき、はためきながら右側から左側へ向かって、たなびいて流れて行く様子のスクリーンショット画像です。


" Ring Fluctuation " を選択してCanvas上をクリックすると、揺らぐ円環状の模様を描画致します。
クリックした点に色とりどりの揺らめく円環模様が現れます。
前述の " Cloth Fluctuation " と類似の処理を行っております。
このピンク ノイズ データは先頭と最後が滑らかに繋がり、循環するようにしてあります。
これにより曲線の始点と終点が繋がり、揺らぐ円環となります。
また、ランダム ウォークで揺らめき、ランダムに拡大縮小を繰り返します。

JS_Art_SS_(2017_05_25)_1_Cropped_1 HTML5インタラクティヴ ジェネレーティヴ ディジタル アートのスクリーンショット画像。 紫色の背景の上に、9つの色とりどりの揺らめく多数の円環状の模様が描かれている。
https://c1.staticflickr.com/5/4275/34029175194_ca3c9ec05e_o.png
これは色とりどりの揺らめく多数の円環状の模様のスクリーンショット画像です。


" Colorful Wave " を選択してCanvas上をクリックすると、時間と共にゆっくりと波打つ様に動く曲線を描画致します。
大した処理はしておりませんが、やや地味ながらも少しばかりの癒やしを感じられるかもしれません。
ところで、HTML5のCanvas要素で暈しを掛けた曲線を多数Canvas画面全域に描画する処理は思いの外、計算負荷が高いものでした。

JS_Art_SS_(2017_05_24)_5_Cropped_1 HTML5インタラクティヴ ジェネレーティヴ ディジタル アートのスクリーンショット画像。 黒い背景の上に、幾本もの太さのまちまちな、光が滲む大きく湾曲した曲線が描かれている。
https://c1.staticflickr.com/5/4252/34832713146_2d9459d849_o.png
これはゆっくりと波打つ曲線を描画した状態のスクリーンショット画像です。
曲線が光り輝いているように見えます。


余談ですが、実は私は以前、このプログラムに運動方程式に基づく三重振り子の物理シミュレーションでカオス図形を描画する機能も組み込んでいたのですが、見た目に満足出来なくなったので、これは削除致しました。


ところで、私はスマートフォンやタブレット PCなどのタッチ スクリーン デヴァイスを所有しておりませんので、タッチ操作時にどのような挙動になるのかという事を検証出来ておりません。
恐らく起こり得る問題やその解消方法は想像出来るのですが、実機で検証出来ない為、手を付けずにおります。

nice!(0)  コメント(0)  トラックバック(0) 

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

※ブログオーナーが承認したコメントのみ表示されます。

Facebook コメント

トラックバック 0