matrix_4x4 m44_view_look_at(vector3 position, vector3 target, vector3 up) { /* Taken From: http://www.opengl.org/wiki/GluLookAt_code */ vector3 zaxis = v3_normalize( v3_sub(target, position) ); vector3 xaxis = v3_normalize( v3_cross(up, zaxis) ); vector3 yaxis = v3_cross(zaxis, xaxis); matrix_4x4 view_matrix = m44_id(); view_matrix.xx = xaxis.x; view_matrix.xy = xaxis.y; view_matrix.xz = xaxis.z; view_matrix.yx = yaxis.x; view_matrix.yy = yaxis.y; view_matrix.yz = yaxis.z; view_matrix.zx = -zaxis.x; view_matrix.zy = -zaxis.y; view_matrix.zz = -zaxis.z; // Also unsure of this. view_matrix = m44_mul_m44(view_matrix, m44_translation(v3_neg(position)) ); return view_matrix; }
mat4_t mat4_look_at(v3_t eye, v3_t center, v3_t up) { v3_t fwd = { center.x - eye.x, center.y - eye.y, center.z - eye.z }; fwd = v3_normalize(fwd); v3_t right = v3_normalize(v3_cross(fwd, up)); up = v3_normalize(v3_cross(right, fwd)); mat4_t v; v.m11 = right.x; v.m12 = right.y; v.m13 = right.z; v.m14 = -v3_scalar(right, eye); v.m21 = up.x; v.m22 = up.y; v.m23 = up.z; v.m24 = -v3_scalar(up, eye); v.m31 = -fwd.x; v.m32 = -fwd.y; v.m33 = -fwd.z; v.m34 = v3_scalar(fwd, eye); v.m41 = 0.f; v.m42 = 0.f; v.m43 = 0.f; v.m44 = 1.f; return v; }
void scotland_update() { camera* cam = entity_get("camera"); light* sun = entity_get("sun"); static_object* skydome = entity_get("skydome"); landscape* world = entity_get("world"); sun_orbit += frame_time() * 0.01; sun->position.x = 512 + sin(sun_orbit) * 512; sun->position.y = cos(sun_orbit) * 512; sun->position.z = 512; sun->target = v3(512, 0, 512); if (w_held || s_held) { vector3 cam_dir = v3_normalize(v3_sub(cam->target, cam->position)); float speed = 0.5; if (!freecam) speed = 0.05; if (w_held) { cam->position = v3_add(cam->position, v3_mul(cam_dir, speed)); } if (s_held) { cam->position = v3_sub(cam->position, v3_mul(cam_dir, speed)); } if (!freecam) { float height = terrain_height(world->terrain, v2(cam->position.x, cam->position.z)); cam->position.y = height + 1; } cam->target = v3_add(cam->position, cam_dir); } Uint8 keystate = SDL_GetMouseState(NULL, NULL); if(keystate & SDL_BUTTON(1)){ float a1 = -(float)mouse_x * 0.005; float a2 = (float)mouse_y * 0.005; vector3 cam_dir = v3_normalize(v3_sub(cam->target, cam->position)); cam_dir.y += -a2; vector3 side_dir = v3_normalize(v3_cross(cam_dir, v3(0,1,0))); cam_dir = v3_add(cam_dir, v3_mul(side_dir, -a1)); cam_dir = v3_normalize(cam_dir); cam->target = v3_add(cam->position, cam_dir); } mouse_x = 0; mouse_y = 0; ui_button* framerate = ui_elem_get("framerate"); ui_button_set_label(framerate, frame_rate_string()); }
t_vec3 v3_frontnormed(float const a[2]) { return (v3_normalize(ATOV3( cos(a[0]) * cos(a[1]) , sin(a[1]) , sin(a[0]) * cos(a[1])))); }
/* Adds a triangle by interpolating over the given edges (which are expected to * contain an intersection). * The edges are specified by their vertices (u is the first edge, v the second, * etc.) */ void interpolate_edges(triangle *triangles, unsigned char isovalue, cell c, int u0, int u1, int v0, int v1, int w0, int w1) { vec3 p1, p2, p3; p1 = interpolate_points(isovalue, c.p[u0], c.p[u1], c.value[u0], c.value[u1]); p2 = interpolate_points(isovalue, c.p[v0], c.p[v1], c.value[v0], c.value[v1]); p3 = interpolate_points(isovalue, c.p[w0], c.p[w1], c.value[w0], c.value[w1]); triangles->p[0] = p1; triangles->p[1] = p2; triangles->p[2] = p3; // the surface-normal is the cross-product between 2 of the edges making up // the face vec3 normal = v3_crossprod(v3_subtract(p1, p2), v3_subtract(p3, p1)); normal = v3_normalize(normal); normal = v3_multiply(normal, -1); triangles->n[0] = normal; triangles->n[1] = normal; triangles->n[2] = normal; }
static void toggle_freecam(ui_button* b, SDL_Event event) { if (event.type == SDL_MOUSEBUTTONDOWN) { if (ui_button_contains_position(b, v2(event.motion.x, event.motion.y))) { b->pressed = true; } } else if (event.type == SDL_MOUSEBUTTONUP) { if (b->pressed) { b->pressed = false; freecam = !freecam; camera* cam = entity_get("camera"); landscape* world = entity_get("world"); vector3 cam_dir = v3_normalize(v3_sub(cam->target, cam->position)); float height = terrain_height(world->terrain, v2(cam->position.x, cam->position.z)); cam->position.y = height + 1; cam->target = v3_add(cam->position, cam_dir); } } }
void triangle_update(triangle_t* triangle) { v3_sub(&triangle->edge1, &triangle->v1, &triangle->v0); v3_sub(&triangle->edge2, &triangle->v2, &triangle->v0); v3_cross(&triangle->normal, &triangle->edge1, &triangle->edge2); v3_normalize(&triangle->normal); }
void metaballs_event(SDL_Event event) { camera* cam = entity_get("camera"); light* sun = entity_get("sun"); switch(event.type){ case SDL_KEYDOWN: break; case SDL_KEYUP: if (event.key.keysym.sym == SDLK_SPACE) { particles_reset(); } if (event.key.keysym.sym == SDLK_w) { wireframe = !wireframe; } break; case SDL_MOUSEBUTTONUP: break; case SDL_MOUSEBUTTONDOWN: if (event.button.button == SDL_BUTTON_WHEELUP) { cam->position = v3_sub(cam->position, v3_normalize(v3_sub(cam->position, cam->target))); } if (event.button.button == SDL_BUTTON_WHEELDOWN) { cam->position = v3_add(cam->position, v3_normalize(v3_sub(cam->position, cam->target))); } break; case SDL_MOUSEMOTION: mouse_x = event.motion.xrel; mouse_y = event.motion.yrel; break; } }
// Check if the given sphere is intersected by the given ray. // See Shirley et.al., section 10.3.1 // Returns 1 if there is an intersection (and sets the appropriate // fields of ip), or 0 otherwise. static int ray_intersects_sphere(intersection_point* ip, sphere sph, vec3 ray_origin, vec3 ray_direction) { float A, B, C, D; vec3 diff; float t_hit; A = v3_dotprod(ray_direction, ray_direction); diff = v3_subtract(ray_origin, sph.center); B = 2.0 * v3_dotprod(diff, ray_direction); C = v3_dotprod(diff, diff) - sph.radius * sph.radius; D = B*B - 4*A*C; if (D < 0.0) return 0; D = sqrt(D); // We're only interested in the first hit, i.e. the one with // the smallest t_hit, so we check -B-D first, followed by -B+D t_hit = (-B - D)/(2*A); if (t_hit < 0.0) { t_hit = (-B + D)/(2*A); if (t_hit < 0.0) return 0; } ip->t = t_hit; ip->p = v3_add(ray_origin, v3_multiply(ray_direction, t_hit)); ip->n = v3_normalize(v3_subtract(ip->p, sph.center)); ip->i = v3_normalize(v3_negate(ray_direction)); ip->material = sph.material; return 1; }
void sea_event(SDL_Event event) { camera* cam = entity_get("camera"); light* sun = entity_get("sun"); switch(event.type) { case SDL_KEYUP: if (event.key.keysym.sym == SDLK_SPACE) { char ball_name[20]; sprintf(ball_name, "ball_%i", ball_count); ball_count++; physics_object* ball = entity_new(ball_name, physics_object); ball->renderable = asset_get("./resources/ball.obj"); ball->collision_body = collision_body_new_sphere(sphere_new(v3_zero(), 1)); ball->position = cam->position; ball->scale = v3(0.5, 0.5, 0.5); ball->velocity = v3_mul(v3_normalize(v3_sub(cam->target, cam->position)), 75); } case SDL_MOUSEBUTTONDOWN: if (event.button.button == SDL_BUTTON_WHEELUP) { cam->position = v3_sub(cam->position, v3_normalize(cam->position)); } if (event.button.button == SDL_BUTTON_WHEELDOWN) { cam->position = v3_add(cam->position, v3_normalize(cam->position)); } break; case SDL_MOUSEMOTION: mouse_x = event.motion.xrel; mouse_y = event.motion.yrel; break; } }
void sea_update() { camera* cam = entity_get("camera"); light* sun = entity_get("sun"); wave_time += frame_time(); static_object* corvette = entity_get("corvette"); corvette->position.y = (sin(wave_time) + 1) / 2; corvette->rotation = v4_quaternion_pitch(sin(wave_time * 1.123) / 50); corvette->rotation = v4_quaternion_mul(corvette->rotation, v4_quaternion_yaw(sin(wave_time * 1.254) / 25)); corvette->rotation = v4_quaternion_mul(corvette->rotation, v4_quaternion_roll(sin(wave_time * 1.355) / 100)); static_object* center_sphere = entity_get("center_sphere"); physics_object* balls[100]; int num_balls; entities_get(balls, &num_balls, physics_object); for(int i = 0; i < num_balls; i++) { physics_object_collide_static(balls[i], center_sphere, frame_time()); physics_object_collide_static(balls[i], corvette, frame_time()); physics_object_update(balls[i], frame_time()); } Uint8 keystate = SDL_GetMouseState(NULL, NULL); if(keystate & SDL_BUTTON(1)) { float a1 = -(float)mouse_x * 0.01; float a2 = (float)mouse_y * 0.01; cam->position = v3_sub(cam->position, cam->target); cam->position = m33_mul_v3(m33_rotation_y( a1 ), cam->position ); cam->position = v3_add(cam->position, cam->target); cam->position = v3_sub(cam->position, cam->target); vector3 rotation_axis = v3_normalize(v3_cross( v3_sub(cam->position, v3_zero()) , v3(0,1,0) )); cam->position = m33_mul_v3(m33_rotation_axis_angle(rotation_axis, a2 ), cam->position ); cam->position = v3_add(cam->position, cam->target); } if(keystate & SDL_BUTTON(3)) { sun->position.x += (float)mouse_y / 2; sun->position.z -= (float)mouse_x / 2; } mouse_x = 0; mouse_y = 0; ui_button* framerate = ui_elem_get("framerate"); ui_button_set_label(framerate, frame_rate_string()); }
void metaballs_update() { camera* cam = entity_get("camera"); light* sun = entity_get("sun"); Uint8 keystate = SDL_GetMouseState(NULL, NULL); if(keystate & SDL_BUTTON(1)){ float a1 = -(float)mouse_x * frame_time() * 0.25; float a2 = (float)mouse_y * frame_time() * 0.25; cam->position = v3_sub(cam->position, cam->target); cam->position = m33_mul_v3(m33_rotation_y( a1 ), cam->position ); cam->position = v3_add(cam->position, cam->target); cam->position = v3_sub(cam->position, cam->target); vector3 rotation_axis = v3_normalize(v3_cross( v3_sub(cam->position, v3_zero()) , v3(0,1,0) )); cam->position = m33_mul_v3(m33_rotation_axis_angle(rotation_axis, a2 ), cam->position ); cam->position = v3_add(cam->position, cam->target); } if(keystate & SDL_BUTTON(3)){ sun->position.x += (float)mouse_y / 2; sun->position.z -= (float)mouse_x / 2; } mouse_x = 0; mouse_y = 0; particles_update(frame_time()); ui_button* framerate = ui_elem_get("framerate"); ui_button_set_label(framerate, frame_rate_string()); #ifdef MARCHING_CUBES marching_cubes_metaball_data( particle_positions_memory(), particles_count() ); marching_cubes_clear(); marching_cubes_update(); #endif #ifdef VOLUME_RENDERER volume_renderer_metaball_data( particle_positions_memory(), particles_count() ); volume_renderer_update(); #endif }
void setcameraview(camera c, float aspectratio) { glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(c.fov,aspectratio,0.1,500.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); //glRotatef(1,1,1,(float)c.roll*360.0f/255.0f); vector3 dir=v3_normalize(v3_sub(c.target,c.eye)); matrix m; m_rotate(dir.x,dir.y,dir.z,(float)c.roll*360.0f/255.0f*(float)radtheta,m); vector3 u; m_xformd(m,c.up,u); gluLookAt(c.eye.x,c.eye.y,c.eye.z, c.target.x,c.target.y,c.target.z, u.x,u.y,u.z); glGetFloatv(GL_MODELVIEW_MATRIX,cam); }
void m_rotate(float ax,float ay,float az,float phi,matrix &m) { matrix m1; vector a; if (ax==0 && ay==0 && az==0) {m_identity(m); return;} v3_make(ax, ay, az, a); v3_normalize(a, a); m_identity(m); m_mults(m, (float)cos(phi), m); m_diadic3(a, a, m1); m_mults(m1, (float)(1-cos(phi)), m1); m_add(m, m1, m); m_cross(a, m1); m_mults(m1, (float)sin(phi), m1); m_add(m, m1, m); m[3][3] = 1.0; }
static void init_noise() { int i; /* calculate random gradients */ for(i=0; i<B; i++) { perm[i] = i; /* .. and initialize permutation mapping to identity */ grad1[i] = (scalar_t)((rand() % (B + B)) - B) / B; grad2[i].x = (scalar_t)((rand() % (B + B)) - B) / B; grad2[i].y = (scalar_t)((rand() % (B + B)) - B) / B; grad2[i] = v2_normalize(grad2[i]); grad3[i].x = (scalar_t)((rand() % (B + B)) - B) / B; grad3[i].y = (scalar_t)((rand() % (B + B)) - B) / B; grad3[i].z = (scalar_t)((rand() % (B + B)) - B) / B; grad3[i] = v3_normalize(grad3[i]); } /* permute indices by swapping them randomly */ for(i=0; i<B; i++) { int rand_idx = rand() % B; int tmp = perm[i]; perm[i] = perm[rand_idx]; perm[rand_idx] = tmp; } /* fill up the rest of the arrays by duplicating the existing gradients */ /* and permutations */ for(i=0; i<B+2; i++) { perm[B + i] = perm[i]; grad1[B + i] = grad1[i]; grad2[B + i] = grad2[i]; grad3[B + i] = grad3[i]; } }
vector3 light_direction(light* l) { return v3_normalize( v3_sub( l->target, l->position ) ); }
void ray_trace(void) { vec3 forward_vector, right_vector, up_vector; int i, j; float image_plane_width, image_plane_height; vec3 color; char buf[128]; struct timeval t0, t1; float time_taken; fprintf(stderr, "Ray tracing ..."); gettimeofday(&t0, NULL); num_rays_shot = num_shadow_rays_shot = num_triangles_tested = num_bboxes_tested = 0; // Compute camera coordinate system from camera position // and look-at point up_vector = v3_create(0, 0, 1); forward_vector = v3_normalize(v3_subtract(scene_camera_lookat, scene_camera_position)); right_vector = v3_normalize(v3_crossprod(forward_vector, up_vector)); up_vector = v3_crossprod(right_vector, forward_vector); // Compute size of image plane from the chosen field-of-view // and image aspect ratio. This is the size of the plane at distance // of one unit from the camera position. image_plane_height = 2.0 * tan(0.5*VFOV/180*M_PI); image_plane_width = image_plane_height * (1.0 * framebuffer_width / framebuffer_height); float bottom, left, Us, Vs; left = -image_plane_width * 0.5; bottom = image_plane_height * 0.5; fprintf(stderr, "%d %d\r\n", framebuffer_height, framebuffer_width); // Loop over all pixels in the framebuffer for (j = 0; j < framebuffer_height; j++) { for (i = 0; i < framebuffer_width; i++) { if(!do_antialiasing){ /* With the formula "b + (t−b) * ((j+ 0.5) / ny)" the vector is calculated. * (t-b) equals the negative image_plane_height */ Us = bottom + (-image_plane_height*(j+0.5)/framebuffer_height); /* using the formula: "l + (r−l) * ((i+ 0.5) / nx)" to calculate the vector * (r-l) equals the image_plane_width. */ Vs = left + (image_plane_width*(i+0.5)/framebuffer_width); /* /* Calculate the vector through the pixel (for "Ray through pixel") * Using the formula "Us * U + Vs * v + n * w" */ vec3 UV = v3_add(v3_multiply(up_vector, Us), v3_multiply(right_vector, Vs)); vec3 ray = v3_add(forward_vector, UV); /* Fills the color */ color = ray_color(0, scene_camera_position, ray); } else { float Us1 = bottom + (-image_plane_height*(j+0.25)/framebuffer_height); float Us2 = bottom + (-image_plane_height*(j+0.75)/framebuffer_height); float Vs1 = left + (image_plane_width*(i+0.25)/framebuffer_width); float Vs2 = left + (image_plane_width*(i+0.75)/framebuffer_width); vec3 UV1 = v3_add(v3_multiply(up_vector, Us1), v3_multiply(right_vector, Vs1)); vec3 UV2 = v3_add(v3_multiply(up_vector, Us2), v3_multiply(right_vector, Vs1)); vec3 UV3 = v3_add(v3_multiply(up_vector, Us1), v3_multiply(right_vector, Vs2)); vec3 UV4 = v3_add(v3_multiply(up_vector, Us2), v3_multiply(right_vector, Vs2)); vec3 color1 = ray_color(0, scene_camera_position, v3_add(forward_vector, UV1)); vec3 color2 = ray_color(0, scene_camera_position, v3_add(forward_vector, UV2)); vec3 color3 = ray_color(0, scene_camera_position, v3_add(forward_vector, UV3)); vec3 color4 = ray_color(0, scene_camera_position, v3_add(forward_vector, UV4)); color = v3_multiply( v3_add(v3_add(color1, color2), v3_add(color3, color4)), 0.25 ); } /* Output pixel color */ put_pixel(i, j, color.x, color.y, color.z); } sprintf(buf, "Ray-tracing ::: %.0f%% done", 100.0*j/framebuffer_height); glutSetWindowTitle(buf); } // Done! gettimeofday(&t1, NULL); glutSetWindowTitle("Ray-tracing ::: done"); // Output some statistics time_taken = 1.0 * (t1.tv_sec - t0.tv_sec) + (t1.tv_usec - t0.tv_usec) / 1000000.0; fprintf(stderr, " done in %.1f seconds\n", time_taken); fprintf(stderr, "... %lld total rays shot, of which %d camera rays and " "%lld shadow rays\n", num_rays_shot, do_antialiasing ? 4*framebuffer_width*framebuffer_height : framebuffer_width*framebuffer_height, num_shadow_rays_shot); fprintf(stderr, "... %lld triangles intersection tested " "(avg %.1f tri/ray)\n", num_triangles_tested, 1.0*num_triangles_tested/num_rays_shot); fprintf(stderr, "... %lld bboxes intersection tested (avg %.1f bbox/ray)\n", num_bboxes_tested, 1.0*num_bboxes_tested/num_rays_shot); }
void particles_init() { particle_positions = malloc(sizeof(vector4) * particle_count); particle_velocities = malloc(sizeof(vector4) * particle_count); particle_lifetimes = malloc(sizeof(float) * particle_count); particle_randoms = malloc(sizeof(vector4) * particle_count); srand(time(NULL)); for(int i = 0; i < particle_count; i++) { particle_lifetimes[i] = 999; particle_positions[i] = v4(0,0,0,0); particle_velocities[i] = v4(0,0,0,0); float rx = ((float)rand() / RAND_MAX) * 2 - 1; float ry = ((float)rand() / RAND_MAX) * 2 + 0.5; float rz = ((float)rand() / RAND_MAX) * 2 - 1; float rm = (float)rand() / RAND_MAX; vector3 rand = v3_mul(v3_normalize(v3(rx, ry, rz)), rm * 2); particle_randoms[i] = v4(rand.x, rand.y, rand.z, 0); } glGenBuffers(1, &positions_buffer); glBindBuffer(GL_ARRAY_BUFFER, positions_buffer); glBufferData(GL_ARRAY_BUFFER, sizeof(vector4) * particle_count, particle_positions, GL_DYNAMIC_COPY); glGenBuffers(1, &velocities_buffer); glBindBuffer(GL_ARRAY_BUFFER, velocities_buffer); glBufferData(GL_ARRAY_BUFFER, sizeof(vector4) * particle_count, particle_velocities, GL_DYNAMIC_COPY); glGenBuffers(1, &lifetimes_buffer); glBindBuffer(GL_ARRAY_BUFFER, lifetimes_buffer); glBufferData(GL_ARRAY_BUFFER, sizeof(float) * particle_count, particle_lifetimes, GL_DYNAMIC_COPY); glGenBuffers(1, &randoms_buffer); glBindBuffer(GL_ARRAY_BUFFER, randoms_buffer); glBufferData(GL_ARRAY_BUFFER, sizeof(vector4) * particle_count, particle_randoms, GL_DYNAMIC_COPY); #ifdef OPEN_GL_CPU #ifndef CPU_ONLY k_particle_positions = kernel_memory_allocate(sizeof(vector4) * particle_count); k_particle_velocities = kernel_memory_allocate(sizeof(vector4) * particle_count); k_particle_lifetimes = kernel_memory_allocate(sizeof(float) * particle_count); k_particle_randoms = kernel_memory_allocate(sizeof(vector4) * particle_count); kernel_memory_write(k_particle_positions, sizeof(vector4) * particle_count, particle_positions); kernel_memory_write(k_particle_velocities, sizeof(vector4) * particle_count, particle_velocities); kernel_memory_write(k_particle_lifetimes, sizeof(float) * particle_count, particle_lifetimes); kernel_memory_write(k_particle_randoms, sizeof(vector4) * particle_count, particle_randoms); #endif #else k_particle_positions = kernel_memory_from_glbuffer(positions_buffer); k_particle_velocities = kernel_memory_from_glbuffer(velocities_buffer); k_particle_lifetimes = kernel_memory_from_glbuffer(lifetimes_buffer); k_particle_randoms = kernel_memory_from_glbuffer(randoms_buffer); #endif kernel_program* program = asset_get("./kernels/particles.cl"); float max_life = 60.0; float min_velocity = 0.5; #ifndef CPU_ONLY k_update = kernel_program_get_kernel(program, "particle_update"); kernel_set_argument(k_update, 0, sizeof(kernel_memory), &k_particle_positions); kernel_set_argument(k_update, 1, sizeof(kernel_memory), &k_particle_velocities); kernel_set_argument(k_update, 2, sizeof(kernel_memory), &k_particle_lifetimes); kernel_set_argument(k_update, 3, sizeof(kernel_memory), &k_particle_randoms); kernel_set_argument(k_update, 4, sizeof(cl_float), &max_life); kernel_set_argument(k_update, 5, sizeof(cl_float), &min_velocity); kernel_set_argument(k_update, 9, sizeof(cl_int), &particle_count); #endif }
void ray_trace(void) { vec3 forward_vector, right_vector, up_vector; int i, j; float image_plane_width, image_plane_height; vec3 color; char buf[128]; struct timeval t0, t1; float time_taken; fprintf(stderr, "Ray tracing ..."); gettimeofday(&t0, NULL); num_rays_shot = num_shadow_rays_shot = num_triangles_tested = num_bboxes_tested = 0; // Compute camera coordinate system from camera position // and look-at point up_vector = v3_create(0, 0, 1); forward_vector = v3_normalize(v3_subtract(scene_camera_lookat, scene_camera_position)); right_vector = v3_normalize(v3_crossprod(forward_vector, up_vector)); up_vector = v3_crossprod(right_vector, forward_vector); // Compute size of image plane from the chosen field-of-view // and image aspect ratio. This is the size of the plane at distance // of one unit from the camera position. image_plane_height = 2.0 * tan(0.5*VFOV/180*M_PI); image_plane_width = image_plane_height * (1.0 * framebuffer_width / framebuffer_height); // vector points to the middle of the monitor vec3 plane_center = v3_add(scene_camera_position, forward_vector); // vector points to the left side of the monitor vec3 le_unnormalized = v3_multiply(right_vector, -(image_plane_width / 2.0)); // vector points to the up side of the monitor vec3 up_unnormalized = v3_multiply(up_vector, image_plane_height / 2.0); // vector points to the coordinates 0,0 (left up) of the monitor vec3 left_up = v3_add(plane_center, v3_add(le_unnormalized, up_unnormalized)); // vector points to right, and has length equal to width of a pixel vec3 pixel2pixel_x = v3_multiply(right_vector, (image_plane_width / framebuffer_width)); // vector points to down, and has length equal to height of a pixel vec3 pixel2pixel_y = v3_multiply(up_vector, -(image_plane_height / framebuffer_height)); // ANTI-ALIASING LOOP if (do_antialiasing) { // loop over all pixels in the framebuffer for (j = 0; j < framebuffer_height; j++) { for (i = 0; i < framebuffer_width; i++) { // for each pixel, shoot four rays vec3 ray_direction_00 = v3_add(v3_add(left_up, v3_multiply(pixel2pixel_y, j + 0.25)), v3_multiply(pixel2pixel_x, i + 0.25)); vec3 ray_direction_01 = v3_add(v3_add(left_up, v3_multiply(pixel2pixel_y, j + 0.75)), v3_multiply(pixel2pixel_x, i + 0.25)); vec3 ray_direction_10 = v3_add(v3_add(left_up, v3_multiply(pixel2pixel_y, j + 0.25)), v3_multiply(pixel2pixel_x, i + 0.75)); vec3 ray_direction_11 = v3_add(v3_add(left_up, v3_multiply(pixel2pixel_y, j + 0.75)), v3_multiply(pixel2pixel_x, i + 0.75)); // for each ray fired, get the difference ray_direction_00 = v3_subtract(ray_direction_00, scene_camera_position); ray_direction_01 = v3_subtract(ray_direction_01, scene_camera_position); ray_direction_10 = v3_subtract(ray_direction_10, scene_camera_position); ray_direction_11 = v3_subtract(ray_direction_11, scene_camera_position); // add the colors of the four rays, then divide by four color = ray_color(0, scene_camera_position, ray_direction_00); color = v3_add(color, ray_color(0, scene_camera_position, ray_direction_01)); color = v3_add(color, ray_color(0, scene_camera_position, ray_direction_10)); color = v3_add(color, ray_color(0, scene_camera_position, ray_direction_11)); color = v3_multiply(color, 0.25); // output pixel color put_pixel(i, j, color.x, color.y, color.z); } sprintf(buf, "Ray-tracing (AA enabled) ::: %.0f%% done", 100.0*j/framebuffer_height); glutSetWindowTitle(buf); } } // NON-ANTI-ALIASING LOOP else { // loop over all pixels in the framebuffer for (j = 0; j < framebuffer_height; j++) { for (i = 0; i < framebuffer_width; i++) { // select the currently relevant pixel vec3 ray_direction = v3_add(v3_add(left_up, v3_multiply(pixel2pixel_y, j + 0.5)), v3_multiply(pixel2pixel_x, i + 0.5)); // get diference between the two points ray_direction = v3_subtract(ray_direction, scene_camera_position); // set color color = ray_color(0, scene_camera_position, ray_direction); // output pixel color put_pixel(i, j, color.x, color.y, color.z); } sprintf(buf, "Ray-tracing ::: %.0f%% done", 100.0*j/framebuffer_height); glutSetWindowTitle(buf); } } // set a detailed title, useful for testing if (use_bvh && do_antialiasing) glutSetWindowTitle("Ray-tracing is done. AA=yes, BVH=yes"); else if (use_bvh && !do_antialiasing) glutSetWindowTitle("Ray-tracing is done. AA=no, BVH=yes"); else if (!use_bvh && do_antialiasing) glutSetWindowTitle("Ray-tracing is done. AA=yes, BVH=no"); else glutSetWindowTitle("Ray-tracing is done. AA=no, BVH=no"); // Done! gettimeofday(&t1, NULL); // Output some statistics time_taken = 1.0 * (t1.tv_sec - t0.tv_sec) + (t1.tv_usec - t0.tv_usec) / 1000000.0; fprintf(stderr, " done in %.1f seconds\n", time_taken); fprintf(stderr, "... %d total rays shot, of which %d camera rays and %d shadow rays\n", num_rays_shot, do_antialiasing ? 4*framebuffer_width*framebuffer_height : framebuffer_width*framebuffer_height, num_shadow_rays_shot); fprintf(stderr, "... %d triangles intersection tested (avg %.1f tri/ray)\n", num_triangles_tested, 1.0*num_triangles_tested/num_rays_shot); fprintf(stderr, "... %d bboxes intersection tested (avg %.1f bbox/ray)\n", num_bboxes_tested, 1.0*num_bboxes_tested/num_rays_shot); }
static int ray_intersects_triangle(intersection_point* ip, triangle tri, vec3 ray_origin, vec3 ray_direction) { vec3 edge1, edge2; vec3 tvec, pvec, qvec; double det, inv_det; double t, u, v; // u, v are barycentric coordinates // t is ray parameter num_triangles_tested++; edge1 = v3_subtract(scene_vertices[tri.v[1]], scene_vertices[tri.v[0]]); edge2 = v3_subtract(scene_vertices[tri.v[2]], scene_vertices[tri.v[0]]); pvec = v3_crossprod(ray_direction, edge2); det = v3_dotprod(edge1, pvec); if (det < 1.0e-6) return 0; tvec = v3_subtract(ray_origin, scene_vertices[tri.v[0]]); u = v3_dotprod(tvec, pvec); if (u < 0.0 || u > det) return 0; qvec = v3_crossprod(tvec, edge1); v = v3_dotprod(ray_direction, qvec); if (v < 0.0 || u+v > det) return 0; t = v3_dotprod(edge2, qvec); if (t < 0.0) return 0; inv_det = 1.0 / det; t *= inv_det; u *= inv_det; v *= inv_det; // We have a triangle intersection! // Return the relevant intersection values. // Compute the actual intersection point ip->t = t; ip->p = v3_add(ray_origin, v3_multiply(ray_direction, t)); // Compute an interpolated normal for this intersection point, i.e. // we use the barycentric coordinates as weights for the vertex normals ip->n = v3_normalize(v3_add( v3_add( v3_multiply(tri.vn[0], 1.0-u-v), v3_multiply(tri.vn[1], u) ), v3_multiply(tri.vn[2], v))); ip->i = v3_normalize(v3_negate(ray_direction)); ip->material = tri.material; return 1; }
void ray_trace(void) { vec3 forward_vector, right_vector, up_vector; int i, j; float image_plane_width, image_plane_height; vec3 color; char buf[128]; struct timeval t0, t1; float time_taken; fprintf(stderr, "Ray tracing ..."); gettimeofday(&t0, NULL); num_rays_shot = num_shadow_rays_shot = num_triangles_tested = num_bboxes_tested = 0; // Compute camera coordinate system from camera position // and look-at point up_vector = v3_create(0, 0, 1); forward_vector = v3_normalize(v3_subtract(scene_camera_lookat, scene_camera_position)); right_vector = v3_normalize(v3_crossprod(forward_vector, up_vector)); up_vector = v3_crossprod(right_vector, forward_vector); // Compute size of image plane from the chosen field-of-view // and image aspect ratio. This is the size of the plane at distance // of one unit from the camera position. image_plane_height = 2.0 * tan(0.5*VFOV/180*M_PI); image_plane_width = image_plane_height * (1.0 * framebuffer_width / framebuffer_height); printf("imageplane: (%f, %f)\n", image_plane_width, image_plane_height); // the borders of the image plane in camera coordinates float left = -(image_plane_width / 2), right = image_plane_width / 2, bottom = (image_plane_height / 2), top = -image_plane_height / 2; // rays are expressed as a location vector and direction vector vec3 ray_origin = scene_camera_position; float u, v, w; // Loop over all pixels in the framebuffer for (j = 0; j < framebuffer_height; j++) { for (i = 0; i < framebuffer_width; i++) { vec3 directions[4]; int directions_i = 0; float offsets[2]; int offsets_n; // if anti-aliasing is activated, shoot 4 rays through each pixel // slightly offset from the center if (do_antialiasing) { offsets_n = 2; offsets[0] = 0.25; offsets[1] = 0.75; } // without anti-aliasing, just send a single ray through the // pixel-center else { offsets_n = 1; offsets[0] = 0.5; } // calculate the [u, v, w] components of the pixel's location // relative to the camera for (int u_offset = 0; u_offset < offsets_n; ++u_offset) { for (int v_offset = 0; v_offset < offsets_n; ++v_offset) { w = 1; u = left + (right - left) * (i + offsets[u_offset]) / framebuffer_width; v = bottom + (top - bottom) * (j + offsets[v_offset]) / framebuffer_height; // the direction of the ray is a a linear combination of the camera // basisvectors directions[directions_i] = v3_add3(v3_multiply(forward_vector, w), v3_multiply(right_vector, u), v3_multiply(up_vector, v)); directions_i += 1; } } // Output average pixel color color = v3_create(0.0, 0.0, 0.0); int num_directions = do_antialiasing ? 2 * offsets_n : 1; for (int dir = 0; dir < num_directions; ++dir) { color = v3_add(color, ray_color(0, ray_origin, directions[dir]) ); } color = v3_multiply(color, 1.0 / num_directions); put_pixel(i, j, color.x, color.y, color.z); } sprintf(buf, "Ray-tracing ::: %.0f%% done", 100.0*j/framebuffer_height); glutSetWindowTitle(buf); } // Done! gettimeofday(&t1, NULL); glutSetWindowTitle("Ray-tracing ::: done"); // Output some statistics time_taken = 1.0 * (t1.tv_sec - t0.tv_sec) + (t1.tv_usec - t0.tv_usec) / 1000000.0; fprintf(stderr, " done in %.1f seconds\n", time_taken); fprintf(stderr, "... %d total rays shot, of which %d camera rays and %d shadow rays\n", num_rays_shot, do_antialiasing ? 4*framebuffer_width*framebuffer_height : framebuffer_width*framebuffer_height, num_shadow_rays_shot); fprintf(stderr, "... %d triangles intersection tested (avg %.1f tri/ray)\n", num_triangles_tested, 1.0*num_triangles_tested/num_rays_shot); fprintf(stderr, "... %d bboxes intersection tested (avg %.1f bbox/ray)\n", num_bboxes_tested, 1.0*num_bboxes_tested/num_rays_shot); }
void ray_trace(void) { vec3 forward_vector, right_vector, up_vector; int i, j; float image_plane_width, image_plane_height; vec3 color; char buf[128]; struct timeval t0, t1; float time_taken; fprintf(stderr, "Ray tracing ..."); gettimeofday(&t0, NULL); num_rays_shot = num_shadow_rays_shot = num_triangles_tested = num_bboxes_tested = 0; // Compute camera coordinate system from camera position // and look-at point up_vector = v3_create(0, 0, 1); forward_vector = v3_normalize(v3_subtract(scene_camera_lookat, scene_camera_position)); right_vector = v3_normalize(v3_crossprod(forward_vector, up_vector)); up_vector = v3_crossprod(right_vector, forward_vector); // Compute size of image plane from the chosen field-of-view // and image aspect ratio. This is the size of the plane at distance // of one unit from the camera position. image_plane_height = 2.0 * tan(0.5*VFOV/180*M_PI); image_plane_width = image_plane_height * (1.0 * framebuffer_width / framebuffer_height); vec3 d, e, u, v, w, ud, vd; float l, r, b, t, nx, ny; // direction d, origin e // ONB u, v, w // image plane edges l, r, b, t // window size nx, ny e = scene_camera_position; u = right_vector, v = up_vector, w = v3_negate(forward_vector); l = -0.5 * image_plane_width, r = 0.5 * image_plane_width; b = 0.5 * image_plane_height, t = -0.5 * image_plane_height; nx = framebuffer_width, ny = framebuffer_height; // Loop over all pixels in the framebuffer for (j = 0; j < ny; j++) { for (i = 0; i < nx; i++) { ud = v3_multiply(u, (l + (r - l) * ((i + 0.5) / nx))); vd = v3_multiply(v, (b + (t - b) * ((j + 0.5) / ny))); d = v3_add(v3_add(ud, vd), v3_negate(w)); color = ray_color(0, e, d); put_pixel(i, j, color.x, color.y, color.z); } sprintf(buf, "Ray-tracing ::: %.0f%% done", 100.0*j/framebuffer_height); glutSetWindowTitle(buf); } // Done! gettimeofday(&t1, NULL); glutSetWindowTitle("Ray-tracing ::: done"); // Output some statistics time_taken = 1.0 * (t1.tv_sec - t0.tv_sec) + (t1.tv_usec - t0.tv_usec) / 1000000.0; fprintf(stderr, " done in %.1f seconds\n", time_taken); fprintf(stderr, "... %lld total rays shot, of which %d camera rays and " "%lld shadow rays\n", num_rays_shot, do_antialiasing ? 4*framebuffer_width*framebuffer_height : framebuffer_width*framebuffer_height, num_shadow_rays_shot); fprintf(stderr, "... %lld triangles intersection tested " "(avg %.1f tri/ray)\n", num_triangles_tested, 1.0*num_triangles_tested/num_rays_shot); fprintf(stderr, "... %lld bboxes intersection tested (avg %.1f bbox/ray)\n", num_bboxes_tested, 1.0*num_bboxes_tested/num_rays_shot); }
vector3 egyseg( vector3 a) { vector3 buf; v3_normalize(a,buf); return buf; }