void object_render(object_t* object,camera_t camera) { const color_t white=get_color(255,255,255); int i; vector_t prev_point; vector_t cur_point; prev_point=vector_transform(vector_add(object->position,rotate_vector(object->points[object->num_points-1],object->rotation)),camera); for(i=0;i<object->num_points;i++) { cur_point=vector_transform(vector_add(object->position,rotate_vector(object->points[i],object->rotation)),camera); draw_line((unsigned int)prev_point.x,(unsigned int)prev_point.y,(unsigned int)cur_point.x,(unsigned int)cur_point.y,white); prev_point=cur_point; } }
void simulation_render_lagrange_points(simulation_t* sim,celestial_body_t* secondary) { vector_t lagrange_points[5]; vector_t rel_position=vector_subtract(secondary->base.position,secondary->orbit.primary->base.position); vector_t direction=vector_normalize(rel_position); float a=secondary->base.mass/(secondary->base.mass+secondary->orbit.primary->base.mass); float offset=powf(a*0.3333333,0.333333); lagrange_points[0]=vector_multiply(secondary->orbit.semi_major_axis*(1+offset),direction); lagrange_points[1]=vector_multiply(secondary->orbit.semi_major_axis*(1-offset),direction); lagrange_points[2]=vector_multiply(-secondary->orbit.semi_major_axis*(1+(5.0/12.0)*a),direction); lagrange_points[3].x=rel_position.x*cos(M_PI/3)+rel_position.y*sin(M_PI/3); lagrange_points[3].y=rel_position.x*-sin(M_PI/3)+rel_position.y*cos(M_PI/3); lagrange_points[4].x=rel_position.x*cos(-M_PI/3)+rel_position.y*sin(-M_PI/3); lagrange_points[4].y=rel_position.x*-sin(-M_PI/3)+rel_position.y*cos(-M_PI/3); int i; for(i=0;i<5;i++) { char str[128]; sprintf(str,"%s-%s L%d point",secondary->orbit.primary->name,secondary->name,i+1); vector_t screen_pos=vector_transform(vector_add(secondary->orbit.primary->base.position,lagrange_points[i]),sim->camera); draw_cross(screen_pos,get_color(0,0,255)); draw_text(screen_pos.x+10,screen_pos.y,str); } }
/** * Calculate the minimum bounding box. * \todo Better comparison of floats? */ static void get_bounding_box(const struct transform *t, struct bounding_box *b){ vector_t transformedNormal = vector_transform_direction(PLANE_NORMAL, t); vector_t transformedPoint = vector_transform(vector_set(0, 0, 0), t); for(int i = 0; i < 3; ++i){ if(transformedNormal.f[(i + 1) % 3] == 0 && transformedNormal.f[(i + 2) % 3] == 0){ b->p[0].f[i] = transformedPoint.f[i]; b->p[1].f[i] = transformedPoint.f[i]; }else{ b->p[0].f[i] = -INFINITY; b->p[1].f[i] = INFINITY; } } }
Vector vector_random_hemi_direction_cos_pbrt(Seed * seed, Vector n) { Vector v = vector_random_disk(seed); #if 0 // XXX hack v = vector_scale(v, 0.999); #endif Vector w = {v.x, v.y, sqrt(fmax(0, 1 - v.x * v.x - v.y * v.y))}; Vector x = vector_perpendicular(n); Vector y = cross(n, x); Vector z = n; //return vector_transform(x, y, z, w); return vector_normalize(vector_transform(x, y, z, w)); }
Vector vector_random_hemi_direction_2(Seed * seed, Vector n) { float u = 0; while (u < 0.001) u = random_seed(seed); float v = random_seed(seed); float r = sqrt(1 - u * u); float phi = 2 * M_PI * v; Vector w = vector_polar(phi, r); w.z = u; Vector x = vector_perpendicular(n); Vector y = cross(n, x); Vector z = n; //return vector_transform(x, y, z, w); return vector_normalize(vector_transform(x, y, z, w)); }
Vector vector_random_hemi_direction_cos(Seed * seed, Vector n) { float u = random_seed(seed); float v1 = random_seed(seed); float r = sqrt(u); float phi = 2 * M_PI * v1; Vector v = vector_polar(phi, r); Vector w = {v.x, v.y, sqrt(fmax(0, 1 - v.x * v.x - v.y * v.y))}; Vector x = vector_perpendicular(n); Vector y = cross(n, x); Vector z = n; //return vector_transform(x, y, z, w); return vector_normalize(vector_transform(x, y, z, w)); }
/** * Render a single ray from a camera. * \param s Scene to render. * \param r Ray being cast. * \param wavelength * \param depth How deep are we in the recursion? * \return Energy of the ray. */ static float render_ray(const struct scene *s, struct ray *r, wavelength_t wavelength, int depth){ if(depth > MAX_DEPTH){ return 0; } struct object *obj = NULL; MEASUREMENTS_RAY_SCENE_INTERSECTION(); float distance = kd_tree_ray_intersection(&(s->tree), r, 0, INFINITY, &obj); if(isnan(distance)){ // If the ray didn't hit anything, it stays black. return 0; } vector_t pointInCameraSpace = vector_add(r->origin, vector_multiply(r->direction, distance)); vector_t pointInObjectSpace = vector_transform(pointInCameraSpace, &(obj->invTransform)); vector_t normalInObjectSpace = obj->get_normal(obj, pointInObjectSpace); vector_t normalInCameraSpace = vector_normalize(vector_transform_direction(normalInObjectSpace, &(obj->transform))); #if DOT_PRODUCT_SHADING (void)wavelength; return fabsf(vector_dot(normalInCameraSpace, r->direction)); #else float energy = 0; /// \todo Surface properties shouldn't be in camera space. if(object_is_light_source(obj)){ energy = (obj->light.energy)(pointInCameraSpace, wavelength, normalInCameraSpace, r->direction); } struct outgoing_direction sample = (obj->surface.sample)(pointInCameraSpace, wavelength, normalInCameraSpace, r->direction); struct ray newRay; ray_from_direction(&newRay, pointInCameraSpace, sample.direction); energy += sample.weight * render_ray(s, &newRay, wavelength, depth + 1); return energy; #endif }
int main (int argc, const char *argv[]) { int c; int ok; char *infile, *morphfile, *outfile, *format, *input_layer, *output_layer; char *attrs, *spatial_filter, *attr_filter; int raster, back_transform; extern int optind; extern int optopt; extern char * optarg; if (argc < 2) { printUsage(); return(0); } // Provide default values. infile = morphfile = outfile = input_layer = NULL; attrs = spatial_filter = attr_filter = NULL; format = NULL; raster = 0; output_layer = "transformed_layer"; back_transform = 0; // Process command line while (1) { static struct option long_options[] = { {"help", no_argument, 0, 'h'}, {"input", required_argument, 0, 'i'}, {"morphfile", required_argument, 0, 'm'}, {"output", required_argument, 0, 'o'}, {"format", required_argument, 0, 'f'}, {"raster", no_argument, 0, 'r'}, {"input_layer", required_argument, 0, '1'}, {"spatial_filter", required_argument, 0, 's'}, {"attr_filter", required_argument, 0, 'w'}, {"output_layer", required_argument, 0, '2'}, {"attrs", required_argument, 0, 'a'}, {"back", no_argument, 0, 'b'}, {0, 0, 0, 0} }; c = getopt_long(argc, (char**)argv, "hi:m:o:f:r1:s:w:a:2:b", long_options, NULL); if (c == -1) { break; } switch (c) { case 'h': printUsage(); return 0; case 'i': infile = optarg; break; case 'o': outfile = optarg; break; case 'm': morphfile = optarg; break; case 'f': format = optarg; break; case '1': input_layer = optarg; break; case 's': spatial_filter = optarg; break; case 'a': attrs = optarg; break; case 'w': attr_filter = optarg; break; case '2': output_layer = optarg; break; case 'r': raster = 1; break; case 'b': back_transform = 1; break; case '?': return 1; default: printUsage(); abort(); } } // Input value checking. if (morphfile == NULL) { fprintf(stderr, "Error. You must supply a morph file.\n"); exit(1); } if ((infile == NULL && outfile != NULL) || (infile != NULL && outfile == NULL)) { fprintf(stderr, "Error. Specify an input and an output file.\n"); exit(1); } // Call the appropriate function for transforming the input layer. // If input and output files are not given, read the coordinates from standard input and // write the transformed values to the standard output. if (infile == NULL && outfile == NULL) { ok = coord_transform(morphfile, back_transform); return ok; } printf("r.morph.transform starting\n"); // We have input and output files. Choose between raster and vector. if (raster) { ok = raster_transform(infile, morphfile, outfile, format, back_transform); } else { ok = vector_transform(infile, input_layer, spatial_filter, attr_filter, morphfile, outfile, attrs, format, output_layer, back_transform); } printf("r.morph.transform done\n"); return ok; }
r->invDirection.f[i] = 1 / r->direction.f[i]; } #endif } /** * Transform the ray. * \return The transformed length of the transformed direction vector before * normalization. This value is used to transform intersection distances from * object space to world space. */ float ray_transform(const struct ray * restrict r, const struct transform *restrict t, struct ray *restrict ret){ ret->origin = vector_transform(r->origin, t); ret->direction = vector_transform_direction(r->direction, t); #ifdef DISABLE_SSE float length = vector_length(ret->direction); vector_t dir = vector_divide(ret->direction, length); ret->direction = dir; for(int i = 0; i < 3; ++i){ ret->invDirection.f[i] = 1 / dir.f[i]; } return length; #else vector_t length;
void simulation_render(simulation_t* sim) { const color_t red=get_color(255,0,0); const color_t white=get_color(255,255,255); orbit_t* current_orbit=&sim->current_spacecraft->orbit; //Calculate camera position and orientation sim->camera.position=sim->current_spacecraft->base.position; //vector_t primary_to_cam=vector_subtract(sim->camera.position,current_orbit->primary->base.position); sim->camera.rotation=0;//atan2(primary_to_cam.y,primary_to_cam.x)+M_PI_2; //Plot apoapsis and periapsis vector_t apoapsis=vector_transform(orbit_get_position(current_orbit,current_orbit->longitude_of_periapsis+M_PI),sim->camera); vector_t periapsis=vector_transform(orbit_get_position(current_orbit,current_orbit->longitude_of_periapsis),sim->camera); draw_cross(apoapsis,red); draw_cross(periapsis,red); draw_text(apoapsis.x-20,apoapsis.y-20,"Apoapsis"); draw_text(periapsis.x-20,periapsis.y-20,"Periapsis"); //Render arrow on spacecraft draw_arrow(vector_transform(sim->current_spacecraft->base.position,sim->camera),sim->current_spacecraft->base.rotation+sim->camera.rotation,get_color(0,255,255)); //Show orbit orbit_show(current_orbit,sim->camera,get_color(0,255,0)); char str[64]; //Show speedup if(sim->speedup==1)draw_text(20,650,"Real time"); else { sprintf(str,"Fast forward: %dx",sim->speedup); draw_text(20,650,str); } int i; for(i=0;i<sim->num_celestial_bodies;i++) { //Show orbit if(sim->celestial_bodies[i].orbit.primary!=NULL) { orbit_show(&sim->celestial_bodies[i].orbit,sim->camera,get_color(255,255,0)); simulation_render_lagrange_points(sim,&sim->celestial_bodies[i]); } //Draw planet object_render((object_t*)(&sim->celestial_bodies[i]),sim->camera); //Show name vector_t position=vector_transform(sim->celestial_bodies[i].base.position,sim->camera); draw_text(position.x,position.y,sim->celestial_bodies[i].name); //Draw sphere of influence int j; double theta=0; for(j=0;j<32;j++) { vector_t line_start=sim->celestial_bodies[i].base.position; line_start.x+=sim->celestial_bodies[i].sphere_of_influence*sin(theta); line_start.y+=sim->celestial_bodies[i].sphere_of_influence*cos(theta); line_start=vector_transform(line_start,sim->camera); theta+=M_PI/32; vector_t line_end=sim->celestial_bodies[i].base.position; line_end.x+=sim->celestial_bodies[i].sphere_of_influence*sin(theta); line_end.y+=sim->celestial_bodies[i].sphere_of_influence*cos(theta); line_end=vector_transform(line_end,sim->camera); theta+=M_PI/32; draw_line(line_start.x,line_start.y,line_end.x,line_end.y,white); } } for(i=0;i<sim->num_spacecraft;i++) { object_render((object_t*)(&sim->spacecraft[i]),sim->camera); } render_spacecraft_info(sim->current_spacecraft,50,50); //render_celestial_body_info(sim->current_spacecraft->orbit.primary,500,50); //render_celestial_body_info(&sim->celestial_bodies[5],950,50); }