/* tile_cloud1.c - Don Yang (uguu.org) Works trivially but looks like crap. 09/27/09 */ #include #include #include #include #define DIVISION_COUNT 9 #define IMAGE_SIZE (1 << DIVISION_COUNT) #define TILE_SIZE (IMAGE_SIZE * 2) #define INIT_RANGE 0.1 #define INIT_OFFSET 0.9 #define ROUGHNESS 0.9 #define RandomNumber() (((double)rand()) / (double)RAND_MAX) static double Image[TILE_SIZE][TILE_SIZE]; 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; } /* Mirror horizontally */ for(y = 0; y <= IMAGE_SIZE; y++) { for(x = 1; x < IMAGE_SIZE; x++) Image[y][TILE_SIZE - x] = Image[y][x]; } /* Mirror vertically */ for(y = 1; y < IMAGE_SIZE; y++) { memcpy(&(Image[TILE_SIZE - y][0]), &(Image[y][0]), TILE_SIZE * sizeof(double)); } } /* Write image to stdout */ static void WriteImage() { int x, y, c; printf("P2\n%d %d\n255\n", TILE_SIZE, TILE_SIZE); for(y = 0; y < TILE_SIZE; y++) { for(x = 0; x < TILE_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; }