|
Simulation of DLA(凝集体)
|
|
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);
}
}
}