void trace_image(int width, int height, float aspect, unsigned char *image, const world* world, const vec3& light_dir) { #pragma omp parallel for schedule(dynamic) for(int yloop = 0; yloop < height; yloop++) { unsigned char *row = image + (height - yloop - 1) * (((width * 3) + 3) & ~3); for(int xloop = 0; xloop < width; xloop++) { // printf("%d, %d\n", xloop, yloop); int cols = 0; vec3 color(0, 0, 0); for(int qky = 0; qky < world->ysub; qky++) { for(int qkx = 0; qkx < world->xsub; qkx++) { float u = ((xloop + qkx / (float)world->xsub) + .5) / width; float v = ((yloop + qky / (float)world->ysub) + .5) / height; ray eye_ray; eye_ray.d = make_eye_ray(u, v, aspect, world->cam.fov); eye_ray.o = vec3(0, 0, 0); ray world_ray = transform_ray(eye_ray, world->camera_matrix, world->camera_normal_matrix); vec3 sample = trace(world_ray, world, light_dir); color = vec3_add(color, sample); ++cols; } } vec3 final_color = vec3_divide(color, cols); unsigned char *pixel = row + xloop * 3; pixel[0] = final_color.x * 255; pixel[1] = final_color.y * 255; pixel[2] = final_color.z * 255; } } }
bool sphere::intersect(const ray& ray, const range& r, surface_hit* hit) { float t = sphere_intersect(center, radius, ray, r); if(t == NO_t) return false; if(t > hit->t) return false; if(keep_stats) sphere_shadings++; vec3 point = vec3_add(ray.o, vec3_scale(ray.d, t)); // snap to sphere surface vec3 to_surface = vec3_subtract(point, center); float distance = sqrtf(vec3_dot(to_surface, to_surface)); hit->point = vec3_add(center, vec3_scale(to_surface, radius / distance)); hit->normal = vec3_divide(to_surface, radius); hit->color = color; hit->t = t; return true; }
world *load_world(char *fname) // Get world and return pointer. { char *inpstr; int wkd; std::auto_ptr<world> w(new world); time_t prev = time(NULL); scoped_FILE fp(fopen(fname, "r")); if(fp == NULL) { fprintf(stderr, "Cannot open file %s for input.\nE#%d\n", fname, errno); return NULL; } if((inpstr = getstr(fp)) == NULL) { fprintf(stderr, "Cannot read title.\n"); return NULL; } if(strcmp(inpstr, ".") != 0) { w->Title = NULL; } else { w->Title = new char[strlen(inpstr) + 1]; strcpy(w->Title, inpstr); } // lace now ignored int lace; if(!getint(fp, &lace)) { fprintf(stderr, "*!LACE\n"); return NULL; } int wdth, lnth; // now ignored if(!getint(fp, &wdth)) { fprintf(stderr, "*!WDTH\n"); return NULL; } if(!getint(fp, &lnth)) { fprintf(stderr, "*!LNTH\n"); return NULL; } int xsub, ysub; // now ignored if(!getint(fp, &xsub)) { fprintf(stderr, "*!xsub\n"); return NULL; } if(!getint(fp, &ysub)) { fprintf(stderr, "*!ysub\n"); return NULL; } w->xsub = 1; w->ysub = 1; int r, g, b, brt; if(!getint(fp, &r)) { fprintf(stderr, "*!backgroundr\n"); return NULL; } if(!getint(fp, &g)) { fprintf(stderr, "*!backgroundg\n"); return NULL; } if(!getint(fp, &b)) { fprintf(stderr, "*!backgroundb\n"); return NULL; } if(!getint(fp, &brt)) { fprintf(stderr, "*!backgroundb\n"); return NULL; } w->background.x = r / 16.0 * brt / 100.0; w->background.y = g / 16.0 * brt / 100.0; w->background.z = b / 16.0 * brt / 100.0; int df; if(!getint(fp, &df)) { fprintf(stderr, "*!DIFFUSION\n"); return NULL; } if(!getint(fp, &w->sphere_count)) { fprintf(stderr, "*!#Sphere\n"); return NULL; } prev = time(NULL); w->spheres = new sphere[w->sphere_count]; for(int i = 0; i < w->sphere_count; i++) { if(time(NULL) > prev) { prev = time(NULL); fprintf(stderr, "loaded %u spheres\n", i); } float x, y, z, radius; wkd = fltget(fp, &x) && fltget(fp, &y); wkd = (wkd && fltget(fp, &z) && fltget(fp, &radius)); int r, g, b, brt; wkd = (wkd && getint(fp, &r) && getint(fp, &g)); wkd = (wkd && getint(fp, &b) && getint(fp, &brt)); if(!wkd) { fprintf(stderr, "*!Sphere #%d\n", i); return NULL; } vec3 color(r / 16.0 * brt / 100.0, g / 16.0 * brt / 100.0, b / 16.0 * brt / 100.0); w->spheres[i] = sphere(vec3(x, y, z), radius, color); } w->scene_center = w->spheres[0].center; for(int i = 1; i < w->sphere_count; i++) { w->scene_center = vec3_add(w->spheres[i].center, w->scene_center); } w->scene_center = vec3_divide(w->scene_center, w->sphere_count); w->scene_extent = 0; for(int i = 0; i < w->sphere_count; i++) { vec3 to_center = vec3_subtract(w->scene_center, w->spheres[i].center); float distance = sqrtf(vec3_dot(to_center, to_center)) + w->spheres[i].radius; w->scene_extent = std::max(w->scene_extent, distance); } w->scene_extent *= 2; w->root = make_tree(w->spheres, 0, w->sphere_count); print_tree_stats(); wkd = fltget(fp, &w->cam.eye.x) && fltget(fp, &w->cam.eye.y); wkd = (wkd && fltget(fp, &w->cam.eye.z) && fltget(fp, &w->cam.yaw)); wkd = (wkd && fltget(fp, &w->cam.pitch) && fltget(fp, &w->cam.roll)); wkd = (wkd && fltget(fp, &w->cam.fov)); if(!wkd) { fprintf(stderr, "*!Viewpoint\n"); return NULL; } w->cam.pitch = to_radians(w->cam.pitch); w->cam.yaw = to_radians(w->cam.yaw); w->cam.roll = to_radians(w->cam.roll); w->cam.fov = to_radians(w->cam.fov); return w.release(); }
VEC3 vec3_normalize(VEC3 v) { return vec3_divide(v, vec3_length(v)); }