void predg3f_param(struct predgparam3f_s *pp, const struct predg3f_s *g) { struct vec3f_s p, q, u, v; int za, zb; predg3f_pquv(&p, &q, &u, &v, g); pp->a = vec3f_len(&p) * vec3f_len(&q); pp->b = vec3f_len(&u) * vec3f_len(&v); pp->c = g->c; za = almost_zero(pp->a); zb = almost_zero(pp->b); if (!za || !zb) predg3f_eigen(&pp->q, 0, g); else mat44f_zero(&pp->q); if (!za && !zb) pp->t = ellipsoidal_param_case(pp->a, pp->b, pp->c); else if (!za || !zb) pp->t = toroidal_param_case(pp->a, pp->b, pp->c); else pp->t = inproper_param_case(); }
virtual double intersect(Ray ray) const { Vector edge1 = vertices[1] - vertices[0]; Vector edge2 = vertices[3] - vertices[0]; //Begin calculating determinant - also used to calculate u parameter Vector P = vec(ray.direction, edge2); double det = dot(P, edge1); double inv_det = 1.0 / det; Vector move = ray.start - vertices[0]; double u = dot(move, P) * inv_det; Vector Q = vec(move, edge1); double v = dot(ray.direction, Q) * inv_det; if(almost_zero(det) || u < -EPS || u > 1.0 + EPS || v < -EPS || u + v > 1.0 + EPS) { Vector edge2 = vertices[1] - vertices[2]; Vector edge1 = vertices[3] - vertices[2]; //Begin calculating determinant - also used to calculate u parameter Vector P = vec(ray.direction, edge2); double det = dot(P, edge1); double inv_det = 1.0 / det; Vector move = ray.start - vertices[2]; double u = dot(move, P) * inv_det; Vector Q = vec(move, edge1); double v = dot(ray.direction, Q) * inv_det; if(almost_zero(det) || u < -EPS || u > 1.0 + EPS || v < -EPS || u + v > 1.0 + EPS) { return INFINITY; } double t = dot(edge2, Q) * inv_det; return t; } double t = dot(edge2, Q) * inv_det; return t; }
static void calc_r(struct vec3f_s *r, const struct vec3f_s *v) { if (!almost_zero(v->x)) vec3f_set(r, -v->y, v->x, v->z); /* take x-y plane */ else if (!almost_zero(v->y)) vec3f_set(r, v->x, -v->z, v->y); /* take y-z plane */ else vec3f_set(r, v->z, v->y, -v->x); /* take z-x plane */ }
static void predgparam3f_eval_a_torus(double *t12, double *t23, double *t31, double *t0, const struct predgparam3f_s *pp, double u, double v, int component) { double alpha = u * 2 * PI; double beta = v * 2 * PI; assert(component == 0); if (almost_zero(pp->b)) { double rp = sqrt((pp->a + pp->c) / (2 * pp->a)); double rm = sqrt((pp->a - pp->c) / (2 * pp->a)); *t12 = rp * cos(alpha); *t23 = rp * sin(alpha); *t31 = rm * cos(beta); *t0 = rm * sin(beta); } else { double rp = sqrt((pp->b + pp->c) / (2 * pp->b)); double rm = sqrt((pp->b - pp->c) / (2 * pp->b)); *t12 = rp * cos(alpha); *t23 = rm * sin(alpha); *t31 = rp * cos(beta); *t0 = rm * sin(beta); } }
void main_shadow(void *arg, const color & Kt, const scalar &refraction_thickness, const scalar &cutoff_threshold) { // the light has falled off to almost black, // no need to trace if (almost_black(Cl)) { return; } scalar transp = average(&Kt); // we are less transparent if the surface is treated as two sided if (refraction_thickness > 0.0f) { transp = transp * transp; } // the same with opaque shader if (almost_zero(transp, cutoff_threshold)) { Cl = color(0.0f); Ol = color(1.0f); return; } // reduce the length of ray direction to limit the maximum distance Cl = trace_shadow(P, I - (P - E), Cl) * transp; Ol = (1.0f - transp); }
bool intersectAabb(const Aabb& box, const Ray& ray, floating& a, floating& b) { const Point origin = ray.origin(); const Vector dir = ray.dir(); a = std::numeric_limits<floating>::min(); b = std::numeric_limits<floating>::max(); for (uint8_t i = 0; i < 3; ++i) { if (almost_zero(dir[i])) { if (origin[i] < box.m_p1[i] || origin[i] > box.m_p2[i]) { return false; } continue; } floating idir = 1.0 / dir[i]; floating at = (box.m_p1[i] - origin[i]) * idir; floating bt = (box.m_p2[i] - origin[i]) * idir; if (at > bt) idir = at, at = bt, bt = idir; if (at > a) a = at; if (bt < b) b = bt; if (b < 0 || a > b) return false; } return true; }
enum predgtype3f_e predg3f_type(const struct predg3f_s *g) { struct vec3f_s p, q, u, v; double a, b; int za, zb; predg3f_pquv(&p, &q, &u, &v, g); a = vec3f_len(&p) * vec3f_len(&q); b = vec3f_len(&u) * vec3f_len(&v); za = almost_zero(a); zb = almost_zero(b); if (!za && !zb) return predgtype3f_ellipsoidal; else if (!za || !zb) return predgtype3f_toroidal; else return predgtype3f_inproper; }
static enum predgparamtype3f_e toroidal_param_case(double a, double b, double c) { if (almost_zero(a) && !almost_zero(b)) { if (c >= -b && c <= b) return predgparamtype3f_a_torus; else return predgparamtype3f_an_empty_set; } if (!almost_zero(a) && almost_zero(b)) { if (c >= -a && c <= a) return predgparamtype3f_a_torus; else return predgparamtype3f_an_empty_set; } assert(0); return predgparamtype3f_an_empty_set; }
void enchance_balance() { double factor = -INFINITY; for (int x = 0; x < width; ++x) { for (int y = 0; y < height; ++y) { for (int comp = 0; comp < 3; ++comp) { double cur = buffer[x][y].coord[comp]; if (cur > factor) { factor = cur; } } } } if (almost_zero(factor)) { return; } for (int x = 0; x < width; ++x) { for (int y = 0; y < height; ++y) { buffer[x][y] /= factor; } } };
static int almost_equal(double x, double y) { return almost_zero(x - y); }
static int almost_zero_vector(const struct vec3f_s *v) { return almost_zero(v->x) && almost_zero(v->y) && almost_zero(v->z); }