/* tile_cloud2.c - Don Yang (uguu.org) 09/27/09 */ #include #include #include #define DIVISION_COUNT 9 #define IMAGE_SIZE (1 << DIVISION_COUNT) #define SPIKE_FACTOR 3 #define SPIKE_STEP (IMAGE_SIZE / (1 << SPIKE_FACTOR)) #define SPIKE_COUNT (2 << SPIKE_FACTOR) #define INIT_RANGE 0.2 #define INIT_OFFSET 0.1 #define ROUGHNESS 0.9 #define RandomNumber() (((double)rand()) / (double)RAND_MAX) static double Image[IMAGE_SIZE + 1][IMAGE_SIZE + 1]; static void UpdatePixel(int x, int y, int lock_edges, double value) { if( lock_edges != 0 && (x == 0 || y == 0 || x == IMAGE_SIZE || y == IMAGE_SIZE) ) { return; } Image[y][x] = value; } /* Subdivide image recursively */ static void SubDivide(int init_step, double init_roughness, int lock_edges) { int x, y, cx, cy, nx, ny, step; double displace_scale; displace_scale = init_roughness; for(step = init_step; step > 1;) { step /= 2; for(y = 0; y < IMAGE_SIZE; y = ny) { cy = y + step; ny = cy + step; for(x = 0; x < IMAGE_SIZE; x = nx) { cx = x + step; nx = cx + step; /* Add center point */ UpdatePixel(cx, cy, lock_edges, (Image[y][x] + Image[y][nx] + Image[ny][x] + Image[ny][nx]) / 4.0); /* Add edge points */ UpdatePixel(cx, y, lock_edges, (Image[y][x] + Image[y][nx] + Image[cy][cx]) / 3.0); UpdatePixel(x, cy, lock_edges, (Image[y][x] + Image[cy][cx] + Image[ny][x]) / 3.0); UpdatePixel(nx, cy, lock_edges, (Image[y][nx] + Image[cy][cx] + Image[ny][nx]) / 3.0); UpdatePixel(cx, ny, lock_edges, (Image[cy][cx] + Image[ny][x] + Image[ny][nx]) / 3.0); /* Display newly added points */ UpdatePixel(cx, y, lock_edges, Image[y][cx] + (RandomNumber() - 0.5) * displace_scale); UpdatePixel(x, cy, lock_edges, Image[cy][x] + (RandomNumber() - 0.5) * displace_scale); UpdatePixel(cx, cy, lock_edges, Image[cy][cx] + (RandomNumber() - 0.5) * displace_scale); UpdatePixel(nx, cy, lock_edges, Image[cy][nx] + (RandomNumber() - 0.5) * displace_scale); UpdatePixel(cx, ny, lock_edges, Image[ny][cx] + (RandomNumber() - 0.5) * displace_scale); } } displace_scale *= 0.5; } } static void GenerateImage(void) { int i, x, y; /* First pass: generate base image */ for(y = 0; y <= IMAGE_SIZE; y += SPIKE_STEP) { for(x = 0; x <= IMAGE_SIZE; x += SPIKE_STEP) Image[y][x] = 0.0; } for(i = 0; i < SPIKE_COUNT; i++) { x = (int)(RandomNumber() * IMAGE_SIZE / SPIKE_STEP) * SPIKE_STEP; y = (int)(RandomNumber() * IMAGE_SIZE / SPIKE_STEP) * SPIKE_STEP; Image[y][x] = INIT_OFFSET + INIT_RANGE * RandomNumber(); } SubDivide(SPIKE_STEP, ROUGHNESS / (1 << SPIKE_FACTOR), 0); /* Second pass: tile image */ for(i = 0; i <= IMAGE_SIZE; i++) { Image[IMAGE_SIZE][i] = Image[0][i]; Image[i][IMAGE_SIZE] = Image[i][0]; } SubDivide(IMAGE_SIZE, ROUGHNESS, 1); } /* Write image to stdout */ static void WriteImage() { int x, y, c; printf("P2\n%d %d\n255\n", IMAGE_SIZE, IMAGE_SIZE); for(y = 0; y < IMAGE_SIZE; y++) { for(x = 0; x < IMAGE_SIZE; x++) { c = (int)(Image[y][x] * 255); if( c < 0 ) { (void)puts("0"); } else if( c > 255 ) { (void)puts("255"); } else { printf("%d\n", c); } } } } int main(void) { srand((unsigned)time(NULL)); GenerateImage(); WriteImage(); return 0; }