|
|
Die Bahnwelt の一発芸「ラーカイアの時空転移シーン」では、無数のひび割れのようなアニメーションが表示されます。このひび割れパターンは「凝集体」の成長モデルを参考に計算で作り出したものです。
凝集体というのは、左図のシミュレーションのように分子や原子がランダムウォークしながら、 適当な「種」に結合していくことで、結晶が成長していく様子をモデル化したものです。上のシミュレーションでは 100個の点を結合させるところまで表示しています。これだけでは形もいびつで ちょっとひび割れに見せるには不十分ですが、十分な量を集めると確率的に円形にひび割れが 広がっていきます。
Bahnwelt では、2048 個の点からなる凝集体を1セットとして、複数のセットを球体で囲むように透視変換した約9000個のラインを表示して、右図のような時空転移の表現にしてみたわけです。
凝集体の成長パターンは、見てのとおり不規則です。ランダムウォークする点は本当はランダムに動くはずなのですが、これでは永遠に種に結合しないかもしれませんので、中央に向かうように乱数に偏向をかけています。また、点の出現位置は種から360°周囲に発生させていますが、これを特定の角度に範囲を狭めれば、そちらの方向に伸びる例えば稲妻のようなパターンになるでしょう。
ちなみに、2000個の点による凝集体が成長してデータを取得するまで、これを X68000 10MHzで何時間かかったことか・・・
/* * DLA Simulation * by H.Kuwata '92/4/14 */ #define segment_max 2048 int segment_count; struct segment_list { char sx,sy; char x,y; } segment[4096]; short segment_mapping[256][256]; segment_regist(int x, int y, int sx, int sy) { segment[segment_count].x = x; segment[segment_count].y = y; segment[segment_count].sx = sx; segment[segment_count].sy = sy; segment_mapping[x+128][y+128] = ++segment_count; // line draw s{x,y} - {x,y} __draw_registed_segment(sx, sy, x, y); } void aggregates_simulation(float radius) { int r, i ,k; // clear segment_count = 0; for (i=0; i<256; i++) { for (k=0; k<256; k++) { segment_mapping[i][k] = 0; } } // center seed segment_regist(0, 0, 0, 0); // simulate and regist segment for (i = 1; i < segment_max; i++) { // start position float th = __random_value() * 3.141592 * 2; float px = r * cos(th); float py = r * sin(th); for (;;) { // approach to center float xx = px + 2*(rand() - 0.5) - (px / 150.); float yy = py + 2*(rand() - 0.5) - (py / 150.); int nx = (int)xx; int ny = (int)yy; // if contact, regist segment if (segment_mapping[nx+128][ny+128]) { segment_regist((int)px, (int)py, nx, ny); break; } // move walker point px = xx; py = yy; __put_walker_point(px,py); } } }