hit_test intersect(ray r, object obj) { v3 ro = r.origin; v3 rd = r.direction; double t; hit_test ht_out; switch (obj.tag) { case SPHERE: { v3 sc = obj.o.s.center; double sr = obj.o.s.radius; v3 A = v3_sub(ro, sc); double B = v3_dot(A, rd); double C = v3_dot(A, A) - sr*sr; double D = B*B - C; t = -B - sqrt(D); if (D > 0 && t > 0) { v3 ray_pos = ray_position(r, t); ht_out.miss = HIT; ht_out.t = t; ht_out.hit_point = ray_pos; ht_out.surf = \ (*(obj.o.s.surface_color))(obj.o.s.center, ray_pos); ht_out.shine = obj.o.s.shine; ht_out.surf_norm = v3_norm(v3_sub(ray_pos, obj.o.s.center)); } else { ht_out.miss = MISS; } break; } case POSTER: { v3 n = v3_expr(0, 0, -1); double d = obj.o.p.upper_left.z; t = -(v3_dot(ro, n) + d) / v3_dot(rd, n); v3 ray_pos = ray_position(r, t); if (t > 0 && is_on_poster(ray_pos, obj.o.p)) { ht_out.miss = HIT; ht_out.t = t; ht_out.hit_point = ray_pos; ht_out.surf = \ (*(obj.o.p.surface_color))(obj.o.p.upper_left, ray_pos); ht_out.shine = obj.o.p.shine; ht_out.surf_norm = n; } else { ht_out.miss = MISS; } break; } default: fprintf(stderr, "error in intersect: unrecognized tag\n"); exit(1); } return ht_out; }
/* intersect_sphere : intersect func for spheres */ hit_test intersect_sphere(ray r, object obj) { sphere s = obj.o.s; hit_test result; xyz A = xyz_sub(r.origin, s.center); double B = xyz_dot(A, xyz_norm(r.dir)); double C = xyz_dot(A, A) - s.radius*s.radius; double D = B*B - C; double t = -B - sqrt(D); ray newr = {r.origin, xyz_norm(r.dir)}; xyz loc = ray_position(newr,t); xyz v = xyz_sub(loc, s.center); xyz norm = xyz_norm(v); if(D<=0 || t<=0) result.miss = MISS; else { result.miss = HIT; result.t = t; result.hit_point = loc; result.surf = s.surface_color(&obj, loc); result.shine = s.shine; result.surf_norm = norm; } return result; }
/* intersect_poster : intersect func for posters */ hit_test intersect_poster(ray r, object obj) { poster p = obj.o.p; hit_test result; xyz n = xyz_expr(0, 0, -1); double d = p.upper_left.z; xyz rd = xyz_norm(r.dir); double t = -(xyz_dot(r.origin, n) + d)/xyz_dot(rd, n); ray newr = {r.origin, rd}; xyz loc = ray_position(newr,t); xyz ul = p.upper_left; if (t>0 && loc.x>=ul.x && loc.x<=(ul.x+p.w) && loc.y<=ul.y && loc.y>=(ul.y-p.h)) { result.miss = HIT; result.t = t; result.hit_point = loc; result.surf = p.surface_color(&obj, loc); result.shine = p.shine; result.surf_norm = n; } else { result.miss = MISS; } return result; }
rgb lighting(scene s, ray r, hit_test h) { rgb result; if (h.miss) return s.bg; vec hit_position = ray_position(r, h.dist); if (shadow(hit_position, s.light, s.spheres)) { result = rgb_modulate(h.surf, s.amb); } else { double dot = vec_dot(h.surf_norm, s.light.direction); double d = double_max(0, dot); rgb diffuse_light = rgb_scale(d, s.light.color); rgb lsum = rgb_add(s.amb, diffuse_light); result = rgb_modulate(h.surf, lsum); } /**** === implement specular reflection here === ****/ if (rgb_nonzero(h.shine)) { rgb ss; vec N = h.surf_norm; vec L = s.light.direction; rgb S = h.shine; vec R = vec_sub( vec_scale(2* vec_dot(N,L),N),L); vec V = vec_neg(r.direction); if (vec_dot(N,L)>0){ ss = rgb_scale( pow( double_max( vec_dot(R,V),0), 6), S); //rgb_print(k); } else ss = rgb_expr(0,0,0); return rgb_add(result,ss); } return result; }
/* color of the intersecting fsphere (if there is one) */ hit_test fintersect(ray r, fsphere s, timestamp ts) { hit_test result = {0}; /* {0} to quiet the compiler */ vec sc = s.center; double sr = s.radius; vec A = vec_sub(r.origin, sc); double B = vec_dot(A, r.direction); double C = vec_dot(A, A) - (sr * sr); double D = (B * B) - C; double t = (-B - sqrt(D)); result.miss = 1; if (D > 0 && t > 0) { result.miss = 0; result.dist = t; result.surf = s.compute_surf(s.center, ray_position(r,t), ts); result.shine = s.compute_shine(ts); result.surf_norm = vec_norm(vec_sub(ray_position(r,t),sc)); } return result; }
hit_test intersect_cylinder (ray r, cylinder c) { hit_test result; v3 rp = v3_expr(r.direction.x,0,r.direction.z); double mp = v3_mag(rp); v3 np = v3_norm(rp); double xbar = r.origin.x - c.center.x; double zbar = r.origin.z - c.center.z; double a = pow(np.x,2) + pow(np.z,2); double b = 2 * ( (xbar*np.x) + (zbar*np.z) ); double c1 = pow(xbar,2) + pow(zbar,2) - pow(c.radius,2); double d = pow(b,2) - (4*a*c1); result.miss = MISS; if(d >= 0) { double t_front = (-b - sqrt(d)) / (2*a); double t_back = (-b + sqrt(d)) / (2*a); v3 p_front = ray_position(r, t_front/mp); v3 p_back = ray_position(r, t_back/mp); if( (t_front < t_back) && (t_front > 0) && (p_front.y >= c.center.y) && (on_cylinder(p_front, c))) { result.miss = HIT; result.t = (t_front/mp); result.hit_point = p_front; result.surf = c.surface_color(c.center, p_front); result.shine = c.shine; v3 c2 = v3_expr(c.center.x, p_front.y, c.center.z); result.surf_norm = v3_norm(v3_sub(p_front,c2)); } else if( (t_back > 0) && (p_back.y >= c.center.y) && (on_cylinder(p_back, c)) ) { result.miss = HIT; result.t = (t_back/mp); result.hit_point = p_back; result.surf = c.surface_color(c.center, p_back); result.shine = c.shine; v3 c3 = v3_expr(c.center.x, p_back.y, c.center.z); result.surf_norm = v3_norm(v3_sub(c3,p_back)); } } return result; }
hit_test intersect_poster (ray r, poster p) { hit_test result = {0}; v3 ro = r.origin; v3 rd = r.direction; v3 n = v3_expr(0, 0, -1); double d = p.upper_left.z; double t = -(v3_dot(ro, n) + d) / v3_dot(rd, n); result.miss = MISS; v3 intersection = ray_position(r, t); if (t>0 && within_poster(intersection, p)) { result.miss = HIT; result.t = t; result.hit_point = intersection; result.surf = p.surface_color(p.upper_left, intersection); result.shine = p.shine; result.surf_norm = n; } return result; }
hit_test intersect_sphere (ray r, sphere s) { hit_test result = {0}; v3 sc = s.center; double sr = s.radius; v3 a = v3_sub(r.origin, sc); double b = v3_dot(a, r.direction); double c = v3_dot(a, a) - (sr * sr); double d = (b * b) - c; double t = -b - sqrt(d); result.miss = MISS; if (d > 0 && t > 0) { v3 intersection = ray_position(r, t); result.miss = HIT; result.t = t; result.hit_point = intersection; result.surf = s.surface_color(sc, intersection); result.shine = s.shine; result.surf_norm = v3_norm(v3_sub(intersection, sc)); } return result; }
color bg = color_expr(0,0,0.25); poster p = poster_expr(xyz_expr(-1.5,1.5,4.5), 3, 3, tex_green, color_expr(0,0,0)); object o1 = {POSTER, {.p = p}, NULL}; obj_list *os = ol_singleton(o1); scene scn; scn.bg = bg; scn.objects = os; stage stg = {cam, scn}; camera tcam = {xyz_expr(0,0,-1), 120, 120}; xyz loc1 = logical_loc(tcam,60,51); xyz loc2 = logical_loc(tcam,1,0); xyz loc3 = logical_loc(tcam,60,80); ray orgray = {cam.loc, xyz_sub(loc1,cam.loc)}; hit_test ht = intersect(orgray, o1); xyz htpt = ray_position(orgray,ht.t); double d1 = dist(xyz_expr(-1.5,1.5,4.5),htpt); double d2 = sqrt(p.w*p.w+p.h*p.h); printf("\n\n *** testing intersect ***\n"); xyz_show(stdout,htpt); hit_test_show(stdout,ht); printf("\n\n *** testing dist ***\n"); printf("%.2lf %2.lf %.2lf\n",d1,d2,d1/d2); color c = color_expr(d1/d2,0,0); color_show(stdout,c); printf("\n\n *** testing logica_loc *** \n");