photon sphere_scatter(photon g, sphere s,double d){ // no absorption g.pos = vec_add(g.pos, scale(d,g.dir)); // normal reflection g.dir = vec_add(g.pos, vec_neg(s.centre)); return g; }
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; }
void ui_set_modelview_matrix(struct matrix *mv) { struct matrix ry, rx, rm; struct vector p, o; struct matrix c, t, r, v; mat_make_rotation_around_y(&ry, ui.rotation); mat_make_rotation_around_x(&rx, ui.tilt); mat_mul_copy(&rm, &ry, &rx); vec_zero(&o); /* look at */ vec_set(&p, 0.f, 0.f, -ui.distance); /* camera position */ mat_rotate(&p, &rm); mat_make_look_at(&c, &o, &p); vec_neg(&p); mat_make_translation_from_vec(&t, &p); mat_mul_copy(&v, &c, &t); mat_make_rotation_around_x(&r, -M_PI/2.); mat_mul_copy(mv, &v, &r); }
__SIMDd _SIMD_neg_pd(__SIMDd a) { #ifdef USE_SSE return _mm_xor_pd(a, _mm_set1_pd(-0.0f)); #elif defined USE_AVX return _mm256_xor_pd(a, _mm_set1_pd(-0.0f)); #elif defined USE_IBM return vec_neg(a); #endif }
mat_t *mat_set_view(vec_t eye, vec_t u, vec_t v, vec_t w, mat_t *a){ mat_t *b = mat_set_trans(vec_neg(eye),mat_new_zero()); mat_set_row(0,u,a); mat_set_row(1,v,a); mat_set_row(2,w,a); mat_set_row(3,vec_new(0,0,0,1),a); mat_set_col(3,vec_new(0,0,0,1),a); mat_mult(a,b); mat_free(b); return a; }
/* Computes the phong hilight */ static void ga_shade_phong(vec_t *color, const ga_material_t *mat,const vec_t *lcolor, const vec_t *ldir, const vec_t *dir, const vec_t *norm, float factor){ vec_t r; float fact; float power; r = vec_sub( vec_scale(2.0f,vec_scale(vec_dot(*norm,*ldir),*norm)), *ldir); if((fact = vec_dot(r,vec_neg(*dir))) > 0.0f){ power = powf(fact,mat->spec_power)*mat->spec_factor; *color = vec_add(*color, vec_scale( power*factor, vec_mult(mat->spec_color,*lcolor))); } }
double sphere_distance(photon g, sphere s){ // (centre-x)^2=radius^2 // x=pos+l*dir // solve this quadratic system for l, the path length to intersection double a = dot(g.dir,g.dir); //for clarity, will optimise away double b = 2*dot(g.dir,vec_add(g.pos,vec_neg(s.centre))); double c = dot(s.centre,s.centre) - s.radius*s.radius - 2*dot(g.pos,s.centre); double discriminant = b*b-4*a*c; printf("sphere distance dis=%e\n",discriminant); // if the ray doesn't intersect the object the system has no real solution if (discriminant<0) return 0; puts("hit sphere!"); // if there is a solution we want the smallest positive root // for the moment assume we are not inside (otherwise pick the other root) return (-b-sqrt(discriminant))/(2*a); }
// This function is adapted from geom.cpp in ODE, which // is copyright Russell Smith. // given two line segments A and B with endpoints a1-a2 and b1-b2, return the // points on A and B that are closest to each other (in cp1 and cp2). // in the case of parallel lines where there are multiple solutions, a // solution involving the endpoint of at least one line will be returned. // this will work correctly for zero length lines, e.g. if a1==a2 and/or // b1==b2. // // the algorithm works by applying the voronoi clipping rule to the features // of the line segments. the three features of each line segment are the two // endpoints and the line between them. the voronoi clipping rule states that, // for feature X on line A and feature Y on line B, the closest points PA and // PB between X and Y are globally the closest points if PA is in V(Y) and // PB is in V(X), where V(X) is the voronoi region of X. void line_segment_closest_points(double a1[3], double a2[3], double b1[3], double b2[3], double cp1[3], double cp2[3]) { double la, lb, k, da1, da2, da3, da4, db1, db2, db3, db4, det; double a1a2[3], b1b2[3], a1b1[3], a1b2[3], a2b1[3], a2b2[3], n[3], tmp[3]; // check vertex-vertex features vec_subt(a1a2, a2, a1); vec_subt(b1b2, b2, b1); vec_subt(a1b1, b1, a1); da1 = vec_dot(a1a2, a1b1); db1 = vec_dot(b1b2, a1b1); if ((da1 <= 0) && (db1 >= 0)) { vec_copy(cp1, a1); vec_copy(cp2, b1); return; } vec_subt(a1b2, b2, a1); da2 = vec_dot(a1a2, a1b2); db2 = vec_dot(b1b2,a1b2); if ((da2 <= 0) && (db2 <= 0)) { vec_copy(cp1, a1); vec_copy(cp2, b2); return; } vec_subt(a2b1, b1, a2); da3 = vec_dot(a1a2, a2b1); db3 = vec_dot(b1b2, a2b1); if ((da3 >= 0) && (db3 >= 0)) { vec_copy(cp1, a2); vec_copy(cp2, b1); return; } vec_subt(a2b2, b2, a2); da4 = vec_dot(a1a2, a2b2); db4 = vec_dot(b1b2, a2b2); if ((da4 >= 0) && (db4 <= 0)) { vec_copy(cp1, a2); vec_copy(cp2, b2); return; } // check edge-vertex features. // if one or both of the lines has zero length, we will never get to here, // so we do not have to worry about the following divisions by zero. la = vec_dot(a1a2, a1a2); if ((da1 >= 0) && (da3 <= 0.0)) { k = da1 / la; vsv_mult(tmp, k, a1a2); vec_subt(n, a1b1, tmp); if (vec_dot(b1b2, n) >= 0.0) { vec_plus(cp1, a1, tmp); vec_copy(cp2, b1); return; } } if ((da2 >= 0) && (da4 <= 0)) { k = da2 / la; vsv_mult(tmp, k, a1a2); vec_subt(n, a1b2, tmp); if (vec_dot(b1b2, n) <= 0.0) { vec_plus(cp1, a1, tmp); vec_copy(cp2, b2); return; } } lb = vec_dot(b1b2, b1b2); if ((db1 <= 0) && (db2 >= 0.0)) { k = -db1 / lb; vsv_mult(tmp, k, b1b2); vec_neg(a1b1); vec_subt(n, a1b1, tmp); if (vec_dot(a1a2, n) >= 0.0) { vec_copy(cp1,a1); vec_plus(cp2, b1, tmp); return; } } if ((db3 <= 0.0) && (db4 >= 0.0)) { k = -db3 / lb; vsv_mult(tmp, k, b1b2); vec_neg(a2b1); vec_subt(n, a2b1, tmp); if (vec_dot(a1a2, n) <= 0.0) { vec_copy(cp1,a2); vec_plus(cp2, b1, tmp); return; } } // it must be edge-edge k = vec_dot(a1a2, b1b2); det = la*lb - k*k; if (det <= 0.0) { // this should never happen, but just in case... vec_copy(cp1, a1); vec_copy(cp2, b1); return; } det = 1.0/det; double alpha = (lb*da1 - k*db1) * det; double beta = ( k*da1 - la*db1) * det; vs_mult(a1a2, alpha); vec_plus(cp1, a1, a1a2); vs_mult(b1b2, beta); vec_plus(cp2, b1, b1b2); }