double intersect(Ray r) { double n_dot_u = normal.dot(r.direction); if ((n_dot_u > -0.00001L) && (n_dot_u < 0.00001L)) { return -1.0L; } double n_dot_p0 = normal.dot(center.sub(r.origin)); return n_dot_p0 / n_dot_u; }
double intersect(Ray r) { // cout << "Sphere intersect()" << endl; V3 distance = r.origin.sub(center); double b = distance.dot(r.direction); double c = distance.dot(distance) - radius2; double d = (b * b) - c; if (d > 0.0L) { return -b - sqrt(d); } else { return -1.0L; } }
bool isInMandelbox2(V3 curr_point) { V3 Zn = V3(0, 0, 0); float dZn = 1.0; bool foundFractal = true; for (int i = 0; i < DEPTH; i++) { boxFold(&Zn); sphereFold(&Zn, dZn); Zn = Scale * Zn + curr_point; dZn = Scale * dZn + 1.0; if (Zn.dot(Zn) > BREAK) { foundFractal = false; break; } } return foundFractal; }
V3 trace(Ray ray, int n, vector <HitRecord>* hits) { if (n > 4) { return V3(); } Body *hit = NULL; double mint = DBL_MAX; // cout << "Body count: " << scene.body_count << endl; for (int i = 0; i < scene.body_count; i++) { Body *candidate = scene.objects[i]; // cout << candidate->shape->intersect(ray) << endl; double t = candidate->shape->intersect(ray); if ((t > 0) && (t <= mint)) { mint = t; hit = candidate; } } if (hit == NULL) { return V3(); } // cout << "hit"; V3 point = ray.origin.add(ray.direction.muls(mint)); V3 normal = hit->shape->getNormal(point); V3 direction = hit->material->bounce(ray, normal); if (direction.dot(ray.direction) > 0.0f) { // if the ray is refractedmove the intersection point a bit in point = ray.origin.add(ray.direction.muls(mint*1.0000001L)); } else { // otherwise move it out to prevent problems with doubleing point // accuracy point = ray.origin.add(ray.direction.muls(mint*0.9999999L)); } hits->push_back(HitRecord(point, hit)); Ray newray = Ray(point, direction); return trace(newray, n+1, hits).mul(hit->material->color).add(hit->material->emission); }
bool isInMandelbox(V3 curr_point, float *dist) { V3 Zn = V3(0, 0, 0); float dZn = 1.0; V3 offset = curr_point; bool foundFractal = true; for (int i = 0; i < DEPTH; i++) { boxFold(&Zn); sphereFold(&Zn, dZn); Zn = Scale * Zn + offset; dZn = Scale * dZn + 1.0; if (Zn.dot(Zn) > BREAK) { foundFractal = false; break; } } *dist = Zn.length() * log((Zn.length())) / fabs(dZn); return foundFractal; }
// Moeller-Trumbore bool Triangle::hit(const Ray& ray, const Ray_Tracer* rt, float t_min, float t_max, Ray_Hit& rh, bool shadow) const { // Absolute Triangle Vertex Positions V3& v0 = m->verts[inds[0]]; V3& v1 = m->verts[inds[1]]; V3& v2 = m->verts[inds[2]]; // Two edges of triangle V3 e0, e1; e0 = v1 - v0; e1 = v2 - v0; V3 p = ray.s.cross(e1); float deter = e0.dot(p); if (deter > -EPSILON && deter < EPSILON) return false; V3 t = ray.o - v0; // Store the inverse to reduce divisions float inv_deter = 1.0 / deter; float u = t.dot(p) * inv_deter; if (u < 0.0 || u > 1.0) return false; V3 q = t.cross(e0); float v = ray.s.dot(q) * inv_deter; if (v < 0.0 || u + v > 1.0) return false; float t_inter = e1.dot(q) * inv_deter; if (t_inter < t_min || t_inter > t_max) { //std::cout << "Cull: " << t_inter << '\t' <<t_min<< '\t' <<t_max<< std::endl; return false; } rh.t = t_inter; rh.col = 0.2*m->mat.col; rh.shape = m; if (shadow || ray.depth >= rt->depth_limit) return true; /* if (is_light) { rh.col = Color(1.0, 1.0, 1.0); return true; } */ V3 int_loc = ray.at(t_inter); // Shadow for (Shape* light : rt->lights) { // BIG ASSUMPTION THAT ALL LIGHTS ARE SPHERES Sphere* sph = static_cast<Sphere*>(light); // Make ray from intersection to light V3 int_to_light = sph->c - int_loc; float dist_to_light = int_to_light.norm(); int_to_light.normalize(); Ray shadow_ray(int_loc + EPSILON*int_to_light, int_to_light, ray.depth + 1); Ray_Hit shadow_hit; if (rt->kd->hit_helper(true, rt->kd->root, shadow_ray, rt, EPSILON, dist_to_light, shadow_hit, true, 0)) { if (!shadow_hit.shape->is_light) { continue; } } float inner = int_to_light.dot(normal); if (inner > 0.0) { rh.col += sph->mat.col *inner* m->mat.diff * m->mat.col; } } // Reflection V3 refl_dir = ray.s - 2.0f * (normal.dot(ray.s)) * normal; Ray refl_ray(int_loc + EPSILON*refl_dir, refl_dir, ray.depth + 1); Ray_Hit refl_hit; if (rt->kd->hit_helper(true, rt->kd->root, refl_ray, rt, EPSILON, FLT_MAX, refl_hit, false, 0)) { //if (rt->trace(refl_ray, EPSILON, FLT_MAX, refl_hit, false)) { rh.col += m->mat.refl*refl_hit.col * refl_hit.shape->mat.col; } return true; }