bool UVSphere::hit(const Ray3D& r, float tmin, float tmax, float time, HitRecord& record) const { Vector3D temp = r.getOrigin() - center; double a = dotProduct(r.getDirection(), r.getDirection()); double b = 2*dotProduct(r.getDirection(), temp); double c = dotProduct(temp, temp) - radius*radius; double disc = b*b -4*a*c; //is there some intersection if(disc > 0.0) { disc = sqrt(disc); double t = (-b - disc) / (2.0*a); if (t < tmin) t = (-b + disc) /(2.0*a); if (t < tmin || t > tmax) return false; record.t = t; record.p = record.texp = (r.getOrigin() + t*r.getDirection()); record.uvw.initFromW((record.p - center) / radius); Vector3D n = (record.p - center) / radius; float twopi = 6.28318530718f; float theta = acos(n.getZ()); float phi = atan2(n.getY(), n.getX()); if (phi < 0.0f) phi+= twopi; float one_over_2pi = .159154943029f; float one_over_pi = .318309886184f; float pi = 3.14159; record.uv = Vector2D(phi*one_over_2pi, (pi-theta)*one_over_pi); record.mat_ptr = material; return true; } return false; }
/** * A ray is represented by l0 + l * t = p * l0 - ray origin * l - ray direction * t - parameter * p - point on plane * A plane is represented by (p - p0) dot n = 0 (because perpendicular) * p0 - a point representing the distance from the origin * n - normal of plane * Solving for t by substituting p gives that * t = [ (p0 - l0) dot n ] / [ l dot n ] */ double Plane::findIntersection(const Ray3D & ray) const { Vector3D rayDirection = ray.getDirection(); Vector3D l = rayDirection; Vector3D n = normal; double ldotn = l.dotProduct(n); if (0 == ldotn) { // Ray is || to plane return -1; // Never intersects } else { Vector3D p0 = normal * distance; Vector3D l0 = ray.getOrigin(); double numerator = (p0 - l0).dotProduct(n); return numerator / ldotn; } }
bool UVSphere::shadowHit(const Ray3D& r, float tmin, float tmax, float time) const { Vector3D temp = r.getOrigin() - center; double a = dotProduct(r.getDirection(), r.getDirection()); double b = 2*dotProduct(r.getDirection(), temp); double c = dotProduct(temp, temp) - radius*radius; double disc = b*b -4*a*c; //is there some intersection if(disc > 0.0) { disc = sqrt(disc); double t = (-b - disc) / (2.0*a); if (t < tmin) t = (-b + disc) /(2.0*a); if (t < tmin || t > tmax) return false; return true; } return false; }
Color RayTracer::traceRay (Ray3D ray, float distance) { Primitive* closestPrim = NULL; float newDistance; Color color (0.0, 0.0, 0.0); for (int i = 0; i < _scene->getNumberOfPrimitives (); i++) { newDistance = _scene->getPrimitive (i)->findIntersectionWith (ray, distance); if ((newDistance >= 0.0) && (newDistance < distance)) { closestPrim = _scene->getPrimitive (i); distance = newDistance; } } if (closestPrim == NULL) { return color; } if (closestPrim->getIsLight ()) { color = closestPrim->getColor (); return color; } // calculate diffuse lighting Vector3 pointOfIntersection = ray.getDirection () * distance + ray.getOrigin (); Vector3 normal = closestPrim->getNormalAt (pointOfIntersection); for (int i = 0; i < _scene->getNumberOfPrimitives (); i++) { Primitive* light = _scene->getPrimitive (i); if (!light->getIsLight ()) { // wait, this isn't actually a light ... continue; } Vector3 lightDir = light->getOrigin () - pointOfIntersection; lightDir.normalize(); float lightCoef = normal.dotProduct (lightDir); color = color + closestPrim->getColor () * light->getColor () * lightCoef; } return color; }
// Return distance from ray origin to intersection // See comments for variables and the equations in Plane.cpp's findIntersection double Triangle::findIntersection(const Ray3D & ray) const { // See if the ray intersects the bounding box // *** With bounding box if (!Object::intersectsBBox(ray)) { return -1; } // First check if the ray intersects with the plane (use same calculations) Vector3D rayDirection = ray.getDirection(); Vector3D rayOrigin = ray.getOrigin(); double ldotn = rayDirection.dotProduct(normal); if (0 == ldotn) { // Ray is || to triangle return -1; } else { Vector3D p0 = normal * distance; double distanceToPlane = (p0 - rayOrigin).dotProduct(normal) / ldotn; // Then see if the point is inside the triangle (3 conditions) // Q is the point of intersection Vector3D Q = (rayDirection * distanceToPlane) + rayOrigin; Vector3D sideCA = epC - epA; Vector3D segQA = Q - epA; // 1. (CA x QA) * n >= 0 if (sideCA.crossProduct(segQA).dotProduct(normal) < 0) { return -1; } Vector3D sideBC = epB - epC; Vector3D segQC = Q - epC; // 2. (BC x QC) * n >= 0 if (sideBC.crossProduct(segQC).dotProduct(normal) < 0) { return -1; } Vector3D sideAB = epA - epB; Vector3D segQB = Q - epB; // 3. (AB x QB) * n >= 0 if (sideAB.crossProduct(segQB).dotProduct(normal) < 0) { return -1; } return distanceToPlane; } }