bool Sphere::intersect(Ray& ray, float& tHit, Intersection* intersect) { vec3 e = ray.pos; vec3 d = ray.dir; float a = d*d; float b = 2*d*(e - this->center); float c = (e - this->center)*(e - this->center) - this->radius*this->radius; if (a == 0) { std::cout << "Ray is just a point!" << std::endl; return false; } float discriminant = b*b - 4*a*c; //float tMin = std::numeric_limits<float>::max(); if (discriminant >= 0) { float tPos = (-b + sqrt(discriminant)) / (2.0f*a); float tNeg = (-b - sqrt(discriminant)) / (2.0f*a); tHit = /*(tNeg<0 && tPos>0)? tPos :*/ tNeg; if (tHit >= ray.tMax || tHit <= ray.tMin) return false; intersect->point = vec3(transform * vec4(ray.evaluate(tHit),1),VW); intersect->normal = vec3(transformTI * vec4(intersect->point - this->center, 0),VW).normalize(); //if (tNeg<0 && tPos>0) { // intersect->normal = -1*intersect->normal; //} intersect->shape = this; return true; } return false; }
bool Triangle::intersect(Ray& ray, float& tHit, Intersection* intersect) { vec3 eye = ray.pos; vec3 dir = ray.dir; float a = v1[VX] - v2[VX], d = v1[VX] - v3[VX], g = dir[VX]; float b = v1[VY] - v2[VY], e = v1[VY] - v3[VY], h = dir[VY]; float c = v1[VZ] - v2[VZ], f = v1[VZ] - v3[VZ], i = dir[VZ]; float j = v1[VX]-eye[VX]; float k = v1[VY]-eye[VY]; float l = v1[VZ]-eye[VZ]; float m = (a*(e*i - h*f) + b*(g*f - d*i) + c*(d*h - e*g)); float t = (f*(a*k - j*b) + e*(j*c - a*l) + d*(b*l - k*c))/-m; if (t < ray.tMin || t > ray.tMax) return false; float gamma = (i*(a*k - j*b) + h*(j*c - a*l) + g*(b*l - k*c)) / m; if (gamma < 0 || gamma > 1) return false; float beta = (j*(e*i - h*f) + k*(g*f - d*i) + l*(d*h - e*g))/m; if (beta < 0 || beta > 1-gamma) return false; tHit = t; intersect->point = ray.evaluate(t); intersect->shape = this; float mag = (v1-intersect->point).length() + (v2-intersect->point).length() + (v3-intersect->point).length(); intersect->normal = (((v1-intersect->point).length()/mag)*n1 + ((v2-intersect->point).length()/mag)*n2 + ((v3-intersect->point).length()/mag)*n3).normalize(); return true; }
std::unique_ptr<Intersection> Sphere::intersect(const Ray& ray) { auto p = ray.p - center; auto d = ray.d; float dp = d.dot(p); float dd = d.dot(d); float pp = p.dot(p); float discr = (dp*dp) - (dd*(pp-(radius*radius))); if (discr < 0) { return nullptr; } else { // Find both intersections float t0 = (-dp - sqrt(discr)) / dd; float t1 = (-dp + sqrt(discr)) / dd; // Entire sphere is behind camera if (t1 < 0) return nullptr; // Front of sphere is behind camera float t = t0 < 0 ? t1 : t0; // Calculate surface normal auto n = (ray.evaluate(t) - center).normalized(); return std::unique_ptr<Intersection>(new Intersection(this, n, t)); } }
glm::vec3 Sphere::collisionNormal( const Ray& ray ) const { float time = intersect( ray ); if( time == inf ) return glm::vec3(); return glm::normalize( ray.evaluate( time ) - center ); }
Color Scene::shade(const Ray& ray, const Intersection& hit, int depth, bool shadows, bool kd) const { auto p = ray.evaluate(hit.t); auto n = hit.normal; return (hit.hit)->shade(ray, p, n, light, *this, depth, shadows, kd); }