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; } }
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; } }
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])); }