/* generate_env_map1.c - Don Yang (uguu.org) 09/20/09 */ #include #include #include #include #include #define OUTPUT_SIZE 512 #define BASE_SIZE 1024 #define RandDouble() (((double)rand()) / (double)RAND_MAX) typedef union { unsigned char c[3]; unsigned int x; } Pixel; /* Convert value from one range to another */ static double ConvertRange(double input0, double input1, double output0, double output1, double x) { return ((output1 - output0) * (x - input0) / (input1 - input0)) + output0; } /* Set pixel color based on intensity */ static void SetPixel(double intensity, /*@out@*/Pixel *output) { if( intensity < 0.5 ) { output->c[0] = output->c[1] = (unsigned char)0; output->c[2] = (unsigned char)(intensity * 2.0 * 255); } else if( intensity > 1.0 ) { output->c[0] = output->c[1] = output->c[2] = (unsigned char)255; } else { output->c[0] = output->c[1] = (unsigned char)((intensity - 0.5) * 2.0 * 255); output->c[2] = (unsigned char)255; } } /* Generate base image */ static double *GenerateBaseMap(int base_size) { double p, *image; int i, x, y, s, ix, iy; /* Allocate image */ image = (double*)malloc(base_size * base_size * sizeof(double)); assert(image != NULL); /* Fill background with uniform gray */ for(i = 0; i < base_size * base_size; i++) image[i] = 0.25; /* Generate random squares */ for(i = 0; i < 256; i++) { s = (int)(RandDouble() * base_size * 0.03) + base_size * 0.02; x = (int)(RandDouble() * base_size); y = (int)(RandDouble() * base_size); p = RandDouble() * 0.2 + 0.2; for(iy = -s; iy <= s; iy++) { if( y + iy < 0 ) continue; if( y + iy >= base_size ) break; for(ix = -s; ix <= s; ix++) { if( x + ix < 0 ) continue; if( x + ix >= base_size ) break; image[(y + iy) * base_size + x + ix] += p; } } } return image; } /* Select pixels from base image for output image */ static Pixel *GenerateOutputMap(double *base_image, int base_size, int output_size) { double dx, dy, r2; int x, y, tx, ty; Pixel *image, *p; /* Allocate image */ image = (Pixel*)malloc(output_size * output_size * sizeof(Pixel)); assert(image != NULL); p = image; for(y = 0; y < output_size; y++) { dy = ConvertRange(0, output_size - 1, -1.0, 1.0, y); for(x = 0; x < output_size; x++) { dx = ConvertRange(0, output_size - 1, -1.0, 1.0, x); r2 = dx * dx + dy * dy; if( r2 > 1.0 ) { SetPixel(0.0, p); p++; continue; } tx = (int)ConvertRange(-5.0, 5.0, 0, base_size - 1, dx / sqrt(1 - r2)); ty = (int)ConvertRange(-5.0, 5.0, 0, base_size - 1, dy / sqrt(1 - r2)); if( tx < 0 ) tx = 0; if( tx >= base_size ) tx = base_size - 1; if( ty < 0 ) ty = 0; if( ty >= base_size ) ty = base_size - 1; SetPixel(base_image[ty * base_size + tx], p); p++; } } return image; } /* Write image to output */ static void WriteImage(const Pixel *image, int width, int height, FILE *output) { int x, y; fprintf(output, "P3\n%d %d\n255\n", width, height); for(y = 0; y < height; y++) { for(x = 0; x < width; x++) { fprintf(output, "%d %d %d\n", (int)(image->c[0]), (int)(image->c[1]), (int)(image->c[2])); image++; } } } int main(void) { double *base_image; Pixel *output_image; srand((unsigned)time(NULL)); base_image = GenerateBaseMap(BASE_SIZE); output_image = GenerateOutputMap(base_image, BASE_SIZE, OUTPUT_SIZE); WriteImage(output_image, OUTPUT_SIZE, OUTPUT_SIZE, stdout); free(base_image); free(output_image); return 0; }