void Sphere::intersect(HitRecord& hit, const RenderContext& rc, const Ray& ray)const{ /*float a = dot(ray.d(), ray.d()); Vector v = ray.p()-p;/*Vector(ray.p().x(), ray.p().y(), ray.p().z());*/ /*float b = 2 * dot(ray.d(), v); float c = dot(v, v) - r2(); float disc = b * b - 4 * a * c; if (disc < 0.f){ hit.hit(std::numeric_limits<float>::infinity(), this, material); return; } float distSqrt = sqrtf(disc); float q; if (b < 0) q = (-b - distSqrt)/2.0f; else q = (-b + distSqrt)/2.0f; float t0 = q / a; float t1 = c / q; if (t0 > t1){ float temp = t0; t0 = t1; t1 = temp; } if (t1 < 0) hit.hit(std::numeric_limits<float>::infinity(), this, material); if (t0 < 0) hit.hit(t1, this, material); else hit.hit(t0, this, material);*/ Vector dist = ray.p() - p; float b = dot(dist, ray.d()); float c = dot(dist, dist) - r2(); float d = b*b - c; float t = d > 0 ? -b - sqrt(d) : std::numeric_limits<float>::infinity(); hit.hit(t, this, this->material); }
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()); } }
double Triangle::ix( const Ray& r ) { // Moeller, Trumbore: Fast, minimum storage ray/triangle intersection Vector e1 = p1( r.t0() ) - p0( r.t0() ); Vector e2 = p2( r.t0() ) - p0( r.t0() ); Vector p = r.d().crossProduct( e2 ); double D = e1.dotProduct( p ); if( det < EPS ) return -1; Vector t = r.o() - p0( r.t0() ); double U = t.dotProduct( p ); if( U < EPS || U > D ) // less than check might need to use 0.0 instead of EPS return -1; Vector q = t.crossProduct( e1 ); double V = r.d().dotProduct( q ); if ( V < EPS || U + V > D ) return -1; double t = e1.dotProduct( q ) / D; return t; }
void Plane::intersect(HitRecord& hit, const RenderContext& rc, const Ray& ray)const{ //Vector p(ray.p().x(),ray.p().y(),ray.p().z()); //Vector o(point.x(),point.y(),point.z()); //float d = dot(o, norm); float num = dot(-norm, ray.p()-point); float denom = dot(norm, ray.d()); float t=num/denom; if(denom==0 || num==0 || t<0) hit.hit(std::numeric_limits<float>::infinity(), this, material); else hit.hit(num/denom, this, material); //float num = -(dot(norm,p)+d); //float denom = dot(norm, ray.d()); //if((denom==0 || num==0)) hit.hit(std::numeric_limits<float>::infinity(), this, material); //else hit.hit(num/denom, this, material); }
double Sphere::ix( const Ray &r ) { Point c = p( r.t0() ); Vector oc = ( r.o() - c ); double B = 2.0 * r.d().dotProduct( oc ); double C = pow( oc.m(), 2.0 ) - _R * _R; double temp = B * B - 4 * C; if( temp < EPS ) return -1.0; temp = sqrt( temp ); double D0 = ( -B + temp ) / ( 2 ); double D1 = ( -B - temp ) / ( 2 ); double D; if( D0 > EPS and D1 > EPS ) D = min( D0, D1 ); else if( D0 > EPS ) D = D0; else if( D1 > EPS ) D = D1; else return -1.0; return D; }
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; }