// Shadow ray test. Returns true if shadowed, or false otherwise. // No other information is needed. public bool testShadowRay(double[] origin, double[] dir) { for (int objectIndex = 0; objectIndex < m_numObjects; objectIndex++) { BaseObject obj = m_objects[objectIndex]; double[] coord = new double[3]; if (!RayBox.RayAABB(obj.m_bounds, origin, dir, coord)) // Trivial rejection of whole object { continue; } double[][] tri = new double[3][] { new double[3], new double[3], new double[3] }; for (int i = 0; i < obj.m_numFaces; i++) { getTriangle(objectIndex, i, tri); double t, u, v; if (rayTriangleTest(tri, origin, dir, out t, out u, out v) && t < 1 - m_epsilon) // t < 1 will check the segment. { return(false); } } } return(true); }
// Intersect a ray with the model. The index of the object that is hit is returned (since this is // required to index into the relevant material data). The intersection point is returned (since // the reflected/refracted ray will require this as an origin). The normal is also returned (for computing // local illumination, and for generating the next ray in the path in accordance to the correct distribution). // The normal is interpolated using the barycentric coordinates of the intersection, if the hit object is smooth. // True is returned iff the ray does intersect an object. public bool rayIntersect(double[] origin, double[] dir, out int hitObjectIndex, double[] intersectionPoint, double[] normal) { double tMin = double.MaxValue; double uMin = double.MaxValue; double vMin = double.MaxValue; int nearestObject = -1, nearestTriangle = -1; for (int objectIndex = 0; objectIndex < m_numObjects; objectIndex++) { BaseObject obj = m_objects[objectIndex]; double[] coord = new double[3]; if (!RayBox.RayAABB(obj.m_bounds, origin, dir, coord)) // Trivial rejection of whole object (Bounding Box check) { continue; } double[][] tri = new double[3][] { new double[3], new double[3], new double[3] }; for (int i = 0; i < obj.m_numFaces; i++) { getTriangle(objectIndex, i, tri); double t, u, v; if (rayTriangleTest(tri, origin, dir, out t, out u, out v)) { if (tMin > t) { tMin = t; nearestObject = objectIndex; nearestTriangle = i; uMin = u; vMin = v; } } } } if (nearestObject != -1) // Is there a nearest object, or did the ray just shoot off into infinity? { hitObjectIndex = nearestObject; intersectionPoint[0] = origin[0] + tMin * dir[0]; intersectionPoint[1] = origin[1] + tMin * dir[1]; intersectionPoint[2] = origin[2] + tMin * dir[2]; if (m_objects[nearestObject].m_smooth == false) { Utils.setf3(normal, m_objects[nearestObject].m_normals[nearestTriangle]); // Triangle normal } else { double[][] normals = new double[3][] { new double[3], new double[3], new double[3] }; getNormals(nearestObject, nearestTriangle, normals); double a = 1 - uMin - vMin; double b = uMin; double c = vMin; normal[0] = a * normals[0][0] + b * normals[1][0] + c * normals[2][0]; normal[1] = a * normals[0][1] + b * normals[1][1] + c * normals[2][1]; normal[2] = a * normals[0][2] + b * normals[1][2] + c * normals[2][2]; Utils.normalise(normal); // Interpolated normal } return(true); } else { hitObjectIndex = -1; } return(false); }