int triangle_intersects(const triangle_t *triangle, const ray_t *ray, intersection_t *result) { const v3_t* edge1; const v3_t* edge2; v3_t tvec; v3_t pvec; v3_t qvec; float det; float inv_det; float t; float u; float v; result->hit = 0; //v3_sub(&edge1, &triangle->pt2, &triangle->pt1); //v3_sub(&edge2, &triangle->pt3, &triangle->pt1); edge1 = &triangle->edge1; edge2 = &triangle->edge2; v3_cross(&pvec, &ray->direction, edge2); det = v3_dot(edge1, &pvec); //No culling version if(det > -EPSILON && det < EPSILON) return 0; inv_det = 1.0f / det; v3_sub(&tvec, &ray->origin, &triangle->v0); u = v3_dot(&tvec, &pvec) * inv_det; if(u < 0.0f || u > 1.0f) return 0; v3_cross(&qvec, &tvec, edge1); v = v3_dot(&ray->direction, &qvec) * inv_det; if(v < 0.0f || u + v > 1.0f + EPSILON) //add EPSILON to offset small precision errors return 0; t = v3_dot(edge2, &qvec) * inv_det; if(t > EPSILON) { result->hit = 1; result->distance = t; return 1; } /* v3_copy(&result->normal, &triangle->normal); v3_copy(&result->hit_point, &r->direction); v3_mul_scalar(&result->hit_point, t); v3_add(&result->hit_point, &result->hit_point, &r->origin); */ return 0; }
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; }
Inode *torus_intersect(Prim *p, Ray ro) { double a, b, c, disc, t0, t1; Inode *i0, *i1; Ray r = ray_transform(ro, p->ti); a = v3_sqrnorm(r.d); b = 2 * v3_dot(r.d, r.o); c = v3_sqrnorm(r.o) - 1; if ((disc = SQR(b) - 4 * a * c) <= 0) return (Inode *)0; t0 = (-b - sqrt(disc)) / (2 * a); t1 = (-b + sqrt(disc)) / (2 * a); if (t1 < RAY_EPS) return (Inode *)0; if (t0 < RAY_EPS) { Vector3 n1 = v3_unit(torus_gradient(p, ray_point(r, t1))); return inode_alloc(t1, n1, FALSE); } else { Vector3 n0 = v3_unit(torus_gradient(p, ray_point(ro, t0))); Vector3 n1 = v3_unit(torus_gradient(p, ray_point(ro, t1))); i0 = inode_alloc(t0, n0, TRUE); i1 = inode_alloc(t1, n1, FALSE); i0->next = i1; return i0; } }
int dir_coupling(Cone a, Vector3 v) { if (v3_dot(a.d, v3_scale(-1, v)) > a.cosa) return TRUE; else return FALSE; }
Color ray_shade(int level, Real w, Ray v, RContext *rc, Object *ol) { Inode *i = ray_intersect(ol, v); if (i != NULL) { Light *l; Real wf; Material *m = i->m; Vector3 p = ray_point(v, i->t); Cone recv = cone_make(p, i->n, PIOVER2); Color c = c_mult(m->c, c_scale(m->ka, ambient(rc))); rc->p = p; for (l = rc->l; l != NULL; l = l->next) if ((*l->transport)(l, recv, rc) && (wf = shadow(l, p, ol)) > RAY_WF_MIN) c = c_add(c, c_mult(m->c, c_scale(wf * m->kd * v3_dot(l->outdir,i->n), l->outcol))); if (level++ < MAX_RAY_LEVEL) { if ((wf = w * m->ks) > RAY_WF_MIN) { Ray r = ray_make(p, reflect_dir(v.d, i->n)); c = c_add(c, c_mult(m->s, c_scale(m->ks, ray_shade(level, wf, r, rc, ol)))); } if ((wf = w * m->kt) > RAY_WF_MIN) { Ray t = ray_make(p, refract_dir(v.d, i->n, (i->enter)? 1/m->ir: m->ir)); if (v3_sqrnorm(t.d) > 0) { c = c_add(c, c_mult(m->s, c_scale(m->kt, ray_shade(level, wf, t, rc, ol)))); } } } inode_free(i); return c; } else { return BG_COLOR; } }
t_mat4 m4_look_at(t_vec3 from, t_vec3 to, t_vec3 up) { t_vec3 x; t_vec3 y; t_vec3 z; z = v3_muls(v3_norm(v3_sub(to, from)), -1); x = v3_norm(v3_cross(up, z)); y = v3_cross(z, x); return (mat4( x.x, x.y, x.z, -v3_dot(from, x), y.x, y.y, y.z, -v3_dot(from, y), z.x, z.y, z.z, -v3_dot(from, z), 0, 0, 0, 1 )); }
scalar_t noise3(scalar_t x, scalar_t y, scalar_t z) { int i, j; int bx0, bx1, by0, by1, bz0, bz1; int b00, b10, b01, b11; scalar_t rx0, rx1, ry0, ry1, rz0, rz1; scalar_t sx, sy, sz; scalar_t u, v, a, b, c, d; if(!tables_valid) { init_noise(); tables_valid = 1; } setup(x, bx0, bx1, rx0, rx1); setup(y, by0, by1, ry0, ry1); setup(z, bz0, bz1, rz0, rz1); i = perm[bx0]; j = perm[bx1]; b00 = perm[i + by0]; b10 = perm[j + by0]; b01 = perm[i + by1]; b11 = perm[j + by1]; /* calculate hermite interpolating factors */ sx = s_curve(rx0); sy = s_curve(ry0); sz = s_curve(rz0); /* interpolate along the top slice of the cell */ u = v3_dot(grad3[b00 + bz0], v3_cons(rx0, ry0, rz0)); v = v3_dot(grad3[b10 + bz0], v3_cons(rx1, ry0, rz0)); a = lerp(u, v, sx); u = v3_dot(grad3[b01 + bz0], v3_cons(rx0, ry1, rz0)); v = v3_dot(grad3[b11 + bz0], v3_cons(rx1, ry1, rz0)); b = lerp(u, v, sx); c = lerp(a, b, sy); /* interpolate along the bottom slice of the cell */ u = v3_dot(grad3[b00 + bz0], v3_cons(rx0, ry0, rz1)); v = v3_dot(grad3[b10 + bz0], v3_cons(rx1, ry0, rz1)); a = lerp(u, v, sx); u = v3_dot(grad3[b01 + bz0], v3_cons(rx0, ry1, rz1)); v = v3_dot(grad3[b11 + bz0], v3_cons(rx1, ry1, rz1)); b = lerp(u, v, sx); d = lerp(a, b, sy); /* interpolate between slices */ return lerp(c, d, sz); }
static Real formfactor(int i, int j, int n, Poly **p, Real *a) { Vector3 vi, vj, vji, d; Real r2, ci, cj; vi = poly_centr(p[i]); vj = poly_centr(p[j]); vji = v3_sub(vi, vj); if ((r2 = v3_sqrnorm(vji)) < REL_EPS) return 0; d = v3_scale(1.0/sqrt(r2), vji); if ((cj = v3_dot(poly_normal(p[j]), d)) < REL_EPS) return 0; if ((ci = -v3_dot(poly_normal(p[i]), d)) < REL_EPS) return 0; if (vis_flag && visible(n, p, vj, vji) < REL_EPS) return 0; return a[i] * ((cj * ci) / (PI * r2 + a[i])); }
//get the angle from vector v1 to vector v2 around the axis double GetAngle(double* v1, double* v2, double* axis) { double dot_prod = v3_dot(v1, v2); double r_axis_len = v3_mag(axis); double theta = atan2(r_axis_len, dot_prod); return theta; }
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; }
void makeviewV(void) { Vector3 n,u,v,t; n = view->normal; v = v3_sub(view->up, v3_scale(v3_dot(view->up, n), n)); if (v3_norm(v) < ROUNDOFF) error("view up parallel to view normal"); v = v3_unit(v); u = v3_cross(n, v); t.x = v3_dot(view->center, u); t.y = v3_dot(view->center, v); t.z = v3_dot(view->center, n); view->V = m4_ident(); view->V.r1.x = u.x; view->V.r2.x = v.x; view->V.r3.x = n.x; view->V.r1.y = u.y; view->V.r2.y = v.y; view->V.r3.y = n.y; view->V.r1.z = u.z; view->V.r2.z = v.z; view->V.r3.z = n.z; view->V.r1.w = -t.x; view->V.r2.w = -t.y; view->V.r3.w = -t.z; makeviewVi(); }
Vector3 refract_dir(Vector3 d, Vector3 n, Real eta) { Real c1, c2; if ((c1 = v3_dot(d, n)) < 0) c1 = -c1; else n = v3_scale(-1.0, n); if ((c2 = 1 - SQR(eta) * (1 - SQR(c1))) < 0) return v3_make(0,0,0); else return v3_add(v3_scale(eta, d), v3_scale(eta*c1 - sqrt(c2), n)); }
void camera_setup( camera_t * const c, v3_t eye, v3_t lookat, v3_t up, float fov ) { // compute the basis for the camera // negative look direction from eye to destination v3_t w = v3_norm(v3_sub(eye, lookat)); // compute the side axis v3_t u = v3_norm(v3_cross(up, w)); // and the "up" normal v3_t v = v3_norm(v3_cross(w, u)); m44_t cam = {{ { u.p[0], u.p[1], u.p[2], -v3_dot(u,eye) }, { v.p[0], v.p[1], v.p[2], -v3_dot(v,eye) }, { w.p[0], w.p[1], w.p[2], -v3_dot(w,eye) }, { 0, 0, 0, 1 }, }}; fprintf(stderr, "Camera:\n"); for(int i = 0 ; i < 4 ; i++) { for(int j = 0 ; j < 4 ; j++) fprintf(stderr, " %+5.3f", cam.m[i][j]); fprintf(stderr, "\n"); } // now compute the perspective projection matrix if(1) { float s = 1000.0 / tan(fov * M_PI / 180 / 2); c->near = 1; c->far = 200; float f1 = - c->far / (c->far - c->near); float f2 = - c->far * c->near / (c->far - c->near); m44_t pers = {{ { s, 0, 0, 0 }, { 0, s, 0, 0 }, { 0, 0, f2, -1 }, { 0, 0, f1, 0 }, }}; fprintf(stderr, "Perspective:\n"); for(int i = 0 ; i < 4 ; i++) { for(int j = 0 ; j < 4 ; j++) fprintf(stderr, " %+5.3f", pers.m[i][j]); fprintf(stderr, "\n"); } m44_mult(&c->r, &pers, &cam); } else { // no perspective m44_t pers = {{ { 1, 0, 0, 0 }, { 0, 1, 0, 0 }, { 0, 0, 1, 0 }, { 0, 0, 0, 1 }, }}; // and apply it to the camera matrix to generate transform m44_mult(&c->r, &pers, &cam); } fprintf(stderr, "Cam*Pers\n"); for(int i = 0 ; i < 4 ; i++) { for(int j = 0 ; j < 4 ; j++) fprintf(stderr, " %+5.3f", c->r.m[i][j]); fprintf(stderr, "\n"); } }
Vector3 reflect_dir(Vector3 d, Vector3 n) { return v3_add(d, v3_scale(-2 * v3_dot(n, d), n)); }
GLvoid sample_world() { // int timing; u_int i,j,d; // float t0,t1,t2; v3* temp; v3* disp; // v3* disp2; float dot; float dm; char* temp_s1; char* temp_s2; for (i = 0; i < PARTICLES; i++) { // printf("adding g %d,%f\n", i,ps[i].v[1]); v3_add(ps[i].v, gr); // ps[i].v->v[1] -= g; v3_mult(ps[i].v, LOSS_V); for (d = 0; d < D; d++) { v3_mult_add(ps[i].c, ps[i].v, 1 / (float) SPS); // ps[i].c[d] += ps[i].v[d] / (float) SPS; if (ps[i].c->v[d] < -B + RADIUS) { disp = v3_new(0,0,0); disp->v[d] = ps[i].c->v[d] + B; dm = 1 / (1 - (RADIUS - v3_mag(disp)) / RADIUS); v3_unit(disp); v3_mult_add(ps[i].v, disp, dm * LOSS_WALL * dt); // ps[i].c->v[d] = -B + RADIUS; // ps[i].v->v[d] *= -1 * LOSS_WALL; } if (ps[i].c->v[d] > B - RADIUS) { disp = v3_new(0,0,0); disp->v[d] = ps[i].c->v[d] - B; // dm = (RADIUS - v3_mag(disp)) / RADIUS; dm = 1 / (1 - (RADIUS - v3_mag(disp)) / RADIUS); v3_unit(disp); v3_mult_add(ps[i].v, disp, dm * LOSS_WALL * dt); // ps[i].c->v[d] = B - RADIUS; // ps[i].v->v[d] *= -1 * LOSS_WALL; } } } for (i = 0; i < PARTICLES; i++) { for (j = 0; j < PARTICLES; j++) { if (i == j) continue; if (v3_dist(ps[i].c, ps[j].c) >= RADIUS * 2) continue; /* temp_s1 = v3_str(ps[i].c); temp_s2 = v3_str(ps[j].c); printf("collision pos: %s %s\n", temp_s1, temp_s2); free(temp_s1); free(temp_s2);*/ /* temp_s1 = v3_str(ps[i].v); temp_s2 = v3_str(ps[j].v); printf("collision vel: %s %s\n", temp_s1, temp_s2); free(temp_s1); free(temp_s2); */ temp = v3_copy(ps[i].v); v3_sub(temp, ps[j].v); /* temp_s1 = v3_str(temp); printf("temp = %s\n", temp_s1); free(temp_s1); */ disp = v3_copy(ps[i].c); v3_sub(disp, ps[j].c); // disp2 = v3_copy(disp); dm = RADIUS - v3_mag(disp) / 2; /* temp_s1 = v3_str(disp); printf("disp = %s\n", temp_s1); free(temp_s1); */ v3_unit(disp); /* temp_s1 = v3_str(disp); printf("disp unit = %s\n", temp_s1); free(temp_s1); */ dot = v3_dot(temp, disp); /* printf("dot = %f\n", dot); */ v3_mult_add(ps[i].v, disp, dm*LOSS_COL*dt); v3_mult_sub(ps[j].v, disp, dm*LOSS_COL*dt); // v3_mult_add(ps[i].c, disp, dm); // v3_mult_sub(ps[j].c, disp, dm); v3_del(disp); v3_del(temp); } } }