IntersectionInfo Sphere::rayIntersect(Ray _ray) { Point3f e = _ray.e(); Point3f c = center_; Vector3f d = _ray.d(); float discriminant = dot(d,(e-c))*dot(d,(e-c))- dot(d,d)*(dot((e-c),(e-c))-radius_*radius_); if (discriminant < 0.0) { return IntersectionInfo(0.0, Point3f(), Vector3f(), IntersectionInfo::miss()); } else { float t1 = (dot(d*-1.0,(e-c))+sqrt(discriminant))/dot(d,d); float t2 = (dot(d*-1.0,(e-c))-sqrt(discriminant))/dot(d,d); float t; if (t1 < t2) { t = t1; } else { t = t2; } if (t < _ray.tMin() || t > _ray.tMax()) { return IntersectionInfo(0.0, Point3f(), Vector3f(), IntersectionInfo::miss()); } Point3f p = e + d*t; Vector3f n = 2.0*(p-c); n.normalize(); return IntersectionInfo(t, p, n, IntersectionInfo::hit()); } }
bool MeshShape::intersectTri(const Ray &r, float &t, Vector &p, Vector &n, float &u, float &v) { // Transform the ray for the local transformation matrix Ray rt = _transform.inverse() * Ray(r); Vector A, B, C; float nearest_t = -1.0f, temp_t; int face_index = -1; // Index of intersected face for(unsigned int faceI=0; faceI<mesh->faces.size(); faceI+=3) { A = mesh->vertices[mesh->faces[faceI]]; B = mesh->vertices[mesh->faces[faceI+1]]; C = mesh->vertices[mesh->faces[faceI+2]]; // Skip face if triangle plane and ray are parallel float temp = ((B-A).cross(C-A)).dot(rt.d()); if(temp < eps && temp > -eps) continue; else { double a = A.x() - B.x(); double b = A.y() - B.y(); double c = A.z() - B.z(); double d = A.x() - C.x(); double e = A.y() - C.y(); double f = A.z() - C.z(); double g = rt.d().x(); double h = rt.d().y(); double i = rt.d().z(); double j = A.x() - rt.e().x(); double k = A.y() - rt.e().y(); double l = A.z() - rt.e().z(); double eiSubhf = e*i - h*f; double gfSubdi = g*f - d*i; double dhSubeg = d*h - e*g; double M = a*eiSubhf + b*gfSubdi + c*dhSubeg; double akSubjb = a*k - j*b; double jcSubal = j*c - a*l; double blSubkc = b*l - k*c; // Gamma and Beta represent distance along vectors (c-a) and (b-a) respectively, // if Gamma or Beta are beyond their respective vectors, then intersection is not within the surface of the triangle double Gamma = (i*akSubjb + h*jcSubal + g*blSubkc)/M; if(Gamma < 0 || Gamma > 1) continue; double Beta = (j*eiSubhf + k*gfSubdi + l*dhSubeg)/M; if(Beta < 0 || Beta > (1-Gamma)) continue; temp_t = -((f*akSubjb + e*jcSubal + d*blSubkc)/M); if(temp_t > eps && (nearest_t <= eps || temp_t < nearest_t)) { nearest_t = temp_t; // Retain intersected face index (remember face is specified by i*3,i*3+1,i*3+2) face_index = faceI; } } } // Return intersection details if(nearest_t > eps) { t = nearest_t; p = r.e() + r.d()*t; // Get the intersected triangle vertices A = mesh->vertices[mesh->faces[face_index]]; B = mesh->vertices[mesh->faces[face_index+1]]; C = mesh->vertices[mesh->faces[face_index+2]]; // Compute flat face normal n = _transform.inverse().transpose().mult((B-A).cross(C-A).normalized()).normalized(); Vector pLocal = rt.e() + rt.d()*t; Vector v0 = C - A; Vector v1 = B - A; Vector v2 = pLocal - A; float dot00 = v0.dot(v0); float dot01 = v0.dot(v1); float dot02 = v0.dot(v2); float dot11 = v1.dot(v1); float dot12 = v1.dot(v2); float invDenom = 1.0f / (dot00*dot11 - dot01*dot01); float local_u = (dot11*dot02 - dot01*dot12) * invDenom; float local_v = (dot00*dot12 - dot01*dot02) * invDenom; // Recall faces[face_index] is the index for the vertex, faces[face_index]*2 then maps to the correct u,v position in the uvList since uvList=(u0,v0,u1,v1,...) int uv_index = mesh->faces[face_index]*2; float u_0 = mesh->uvList[uv_index]; float v_0 = mesh->uvList[uv_index+1]; uv_index = mesh->faces[face_index+1]*2; float u_1 = mesh->uvList[uv_index]; float v_1 = mesh->uvList[uv_index+1]; uv_index = mesh->faces[face_index+2]*2; float u_2 = mesh->uvList[uv_index]; float v_2 = mesh->uvList[uv_index+1]; float tu1 = u_1 - u_0; float tv1 = v_1 - v_0; float tu0 = u_2 - u_0; float tv0 = v_2 - v_0; u = u_0 + tu0*local_u + tu1*local_v; v = v_0 + tv0*local_u + tv1*local_v; return true; } else return false; }