バーンウェルト テクニカル (Die Bahnwelt Technical)

□ 凝集体

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);
		}
	}
}