/* cloud2.c - Don Yang (uguu.org) 09/26/09 */ #include #include #include #define DIVISION_COUNT 10 #define IMAGE_SIZE (1 << DIVISION_COUNT) #define INIT_RANGE 0.1 #define INIT_OFFSET 0.9 #define ROUGHNESS 0.9 #define RandomNumber() (((double)rand()) / (double)RAND_MAX) static double Image[IMAGE_SIZE + 1][IMAGE_SIZE + 1]; static void GenerateImage(void) { int x, y, cx, cy, nx, ny, step; double displace_scale; /* Insert spikes at random positions instead of corners. Because the number of spikes is few relative to number of points, most of the texture will be dark. Doing it this way gives us more control than initializing corners. */ for(y = 0; y <= IMAGE_SIZE; y += (IMAGE_SIZE / 4)) { for(x = 0; x <= IMAGE_SIZE; x += (IMAGE_SIZE / 4)) Image[y][x] = 0.0; } for(cx = 0; cx < 16; cx++) { x = (int)(RandomNumber() * IMAGE_SIZE / 4) * 4; y = (int)(RandomNumber() * IMAGE_SIZE / 4) * 4; Image[y][x] = INIT_OFFSET + INIT_RANGE * RandomNumber(); } /* Divide recursively */ displace_scale = ROUGHNESS; for(step = IMAGE_SIZE / 4; step > 1; step /= 2) { for(y = 0; y < IMAGE_SIZE; y = ny) { cy = y + step / 2; ny = y + step; for(x = 0; x < IMAGE_SIZE; x = nx) { cx = x + step / 2; nx = x + step; /* Add center point */ Image[cy][cx] = (Image[y][x] + Image[y][nx] + Image[ny][x] + Image[ny][nx]) / 4.0; /* Add edge points */ Image[y][cx] = (Image[y][x] + Image[y][nx] + Image[cy][cx]) / 3.0; Image[cy][x] = (Image[y][x] + Image[cy][cx] + Image[ny][x]) / 3.0; Image[cy][nx] = (Image[y][nx] + Image[cy][cx] + Image[ny][nx]) / 3.0; Image[ny][cx] = (Image[cy][cx] + Image[ny][x] + Image[ny][nx]) / 3.0; /* Display newly added points */ Image[y][cx] += (RandomNumber() - 0.5) * displace_scale; Image[cy][x] += (RandomNumber() - 0.5) * displace_scale; Image[cy][cx] += (RandomNumber() - 0.5) * displace_scale; Image[cy][nx] += (RandomNumber() - 0.5) * displace_scale; Image[ny][cx] += (RandomNumber() - 0.5) * displace_scale; } } displace_scale *= 0.5; } } /* 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; }