bool Cylinder::Intersect(const Ray &r, Float *tHit, SurfaceInteraction *isect, bool testAlphaTexture) const { Float phi; Point3f pHit; // Transform _Ray_ to object space Vector3f oErr, dErr; Ray ray = (*WorldToObject)(r, &oErr, &dErr); // Compute quadratic cylinder coefficients // Initialize _EFloat_ ray coordinate values EFloat ox(ray.o.x, oErr.x), oy(ray.o.y, oErr.y), oz(ray.o.z, oErr.z); EFloat dx(ray.d.x, dErr.x), dy(ray.d.y, dErr.y), dz(ray.d.z, dErr.z); EFloat a = dx * dx + dy * dy; EFloat b = 2 * (dx * ox + dy * oy); EFloat c = ox * ox + oy * oy - EFloat(radius) * EFloat(radius); // Solve quadratic equation for _t_ values EFloat t0, t1; if (!Quadratic(a, b, c, &t0, &t1)) return false; // Check quadric shape _t0_ and _t1_ for nearest intersection if (t0.UpperBound() > ray.tMax || t1.LowerBound() <= 0) return false; EFloat tShapeHit = t0; if (tShapeHit.LowerBound() <= 0) { tShapeHit = t1; if (tShapeHit.UpperBound() > ray.tMax) return false; } // Compute cylinder hit point and $\phi$ pHit = ray((Float)tShapeHit); // Refine cylinder intersection point Float hitRad = std::sqrt(pHit.x * pHit.x + pHit.y * pHit.y); pHit.x *= radius / hitRad; pHit.y *= radius / hitRad; phi = std::atan2(pHit.y, pHit.x); if (phi < 0) phi += 2 * Pi; // Test cylinder intersection against clipping parameters if (pHit.z < zMin || pHit.z > zMax || phi > phiMax) { if (tShapeHit == t1) return false; tShapeHit = t1; if (t1.UpperBound() > ray.tMax) return false; // Compute cylinder hit point and $\phi$ pHit = ray((Float)tShapeHit); // Refine cylinder intersection point Float hitRad = std::sqrt(pHit.x * pHit.x + pHit.y * pHit.y); pHit.x *= radius / hitRad; pHit.y *= radius / hitRad; phi = std::atan2(pHit.y, pHit.x); if (phi < 0) phi += 2 * Pi; if (pHit.z < zMin || pHit.z > zMax || phi > phiMax) return false; } // Find parametric representation of cylinder hit Float u = phi / phiMax; Float v = (pHit.z - zMin) / (zMax - zMin); // Compute cylinder $\dpdu$ and $\dpdv$ Vector3f dpdu(-phiMax * pHit.y, phiMax * pHit.x, 0); Vector3f dpdv(0, 0, zMax - zMin); // Compute cylinder $\dndu$ and $\dndv$ Vector3f d2Pduu = -phiMax * phiMax * Vector3f(pHit.x, pHit.y, 0); Vector3f d2Pduv(0, 0, 0), d2Pdvv(0, 0, 0); // Compute coefficients for fundamental forms Float E = Dot(dpdu, dpdu); Float F = Dot(dpdu, dpdv); Float G = Dot(dpdv, dpdv); Vector3f N = Normalize(Cross(dpdu, dpdv)); Float e = Dot(N, d2Pduu); Float f = Dot(N, d2Pduv); Float g = Dot(N, d2Pdvv); // Compute $\dndu$ and $\dndv$ from fundamental form coefficients Float invEGF2 = 1 / (E * G - F * F); Normal3f dndu = Normal3f((f * F - e * G) * invEGF2 * dpdu + (e * F - f * E) * invEGF2 * dpdv); Normal3f dndv = Normal3f((g * F - f * G) * invEGF2 * dpdu + (f * F - g * E) * invEGF2 * dpdv); // Compute error bounds for cylinder intersection Vector3f pError = gamma(3) * Abs(Vector3f(pHit.x, pHit.y, 0)); // Initialize _SurfaceInteraction_ from parametric information *isect = (*ObjectToWorld)(SurfaceInteraction(pHit, pError, Point2f(u, v), -ray.d, dpdu, dpdv, dndu, dndv, ray.time, this)); // Update _tHit_ for quadric intersection *tHit = (Float)tShapeHit; return true; }
/*! * Triangle intersection */ bool Triangle::Intersect( const Ray& objectRay, double* tHit, DifferentialGeometry* dg ) const { //e1 = B - A //e2 = C - A Vector3D pVector = CrossProduct( objectRay.direction(), m_vE2 ); double det = DotProduct( m_vE1, pVector ); double inv_det = 1/det; //std::cout<<"det: "<<det<<std::endl; //Vector3D tVector = Vector3D( objectRay.origin ) – Vector3D(m_v1) ; Vector3D tVector = Vector3D( objectRay.origin - m_v1 ); Vector3D qVec = CrossProduct( tVector , m_vE1 ); double thit; double tol = 0.000001; if (det > tol) { double u = DotProduct( tVector,pVector ); if (u < 0 || u > det ) return ( false ); double v = DotProduct( objectRay.direction(), qVec ); if (v < 0 || ( v + u ) > det) return ( false ); double t = DotProduct( m_vE2, qVec ); thit = t * inv_det; u *= inv_det; v *= inv_det; } else if (det < - tol) { double u = DotProduct( tVector, pVector ) * inv_det; if (u < 0.0 || u > 1.0) return ( false ); double v = DotProduct( objectRay.direction(), qVec ) * inv_det; if (v < 0.0 || ( ( v+u ) > 1.0 ) ) return ( false ); double t = DotProduct( m_vE2, qVec ) * inv_det; thit = t; } else return ( false ); //return intersection == true , t, P /*//Jimenez algorithm double t0; double t1; if( !m_bbox.IntersectP(objectRay, &t0, &t1 ) ) return ( false ); //Evaluate Tolerance t0 -= 0.1; t1 += 0.1; Point3D Q1 = objectRay( t0 ); Point3D Q2 = objectRay( t1 ); Vector3D vA = Vector3D( Q1 - m_v3 ); double w = DotProduct( vA, m_vW1 ); Vector3D vD = Vector3D( Q2 - m_v3 ); double s = DotProduct( vD, m_vW1 ); double tol = 0.000001; if( w > tol ) { if( s > tol ) return ( false ); Vector3D vW2 = CrossProduct( vA, vD ); double t = DotProduct( vW2, m_vC ); if( t < -tol ) return ( false ); double u = DotProduct( - vW2, m_vB ); if( u < -tol ) return ( false ); if( w < ( s + t + u ) ) return ( false ); } else if ( w < -tol ) { if( s < -tol ) return ( false ); Vector3D vW2 = CrossProduct( vA, vD ); double t = DotProduct( vW2, m_vC ); if( t > tol ) return ( false ); double u = DotProduct( - vW2, m_vB ); if( u > tol ) return ( false ); if( w > ( s + t + u ) ) return ( false ); } else // w == 0, swap( Q1, Q2 ) { Vector3D vW2 = CrossProduct( vD, vA ); double t = DotProduct( vW2, m_vC ); if( s > tol ) { if( t < -tol ) return ( false ); double u = DotProduct( - vW2, m_vB); if( u < -tol ) return ( false ); if( -s < ( t + u ) ) return ( false ); } else if( s < - tol ) { if( t > tol ) return ( false ); double u = DotProduct( - vW2, m_vB ); if( u > tol ) return ( false ); if( -s > ( t + u ) ) return ( false ); } else return ( false ); } double t_param = ( DotProduct( Normalize( m_vW1 ), vA ) / DotProduct( Normalize( m_vW1 ), Vector3D( Q1 - Q2 ) ) ); double thit = t0 + t_param * Distance( Q1, Q2 ); */ if( thit > *tHit ) return false; if( (thit - objectRay.mint) < tol ) return false; Point3D hitPoint = objectRay( thit ); Vector3D dpdu = Normalize( m_vE1 ); Vector3D dpdv = Normalize( m_vE2 ); // Compute ShapeCone \dndu and \dndv Vector3D d2Pduu( 0.0, 0.0, 0.0 ); Vector3D d2Pduv( 0.0, 0.0, 0.0 ); Vector3D d2Pdvv( 0.0, 0.0, 0.0 ); // Compute coefficients for fundamental forms double E = DotProduct( dpdu, dpdu ); double F = DotProduct( dpdu, dpdv ); double G = DotProduct( dpdv, dpdv ); Vector3D N = Normalize( NormalVector( CrossProduct( dpdu, dpdv ) ) ); double e = DotProduct( N, d2Pduu ); double f = DotProduct( N, d2Pduv ); double g = DotProduct( N, d2Pdvv ); // Compute \dndu and \dndv from fundamental form coefficients double invEGF2 = 1.0 / (E*G - F*F); Vector3D dndu = (f*F - e*G) * invEGF2 * dpdu + (e*F - f*E) * invEGF2 * dpdv; Vector3D dndv = (g*F - f*G) * invEGF2 * dpdu + (f*F - g*E) * invEGF2 * dpdv; // Initialize _DifferentialGeometry_ from parametric information *dg = DifferentialGeometry( hitPoint , dpdu, dpdv, dndu, dndv, -1, -1, 0 ); dg->shapeFrontSide = ( DotProduct( N, objectRay.direction() ) > 0 ) ? false : true; // Update _tHit_ for quadric intersection *tHit = thit; return true; }
bool ShapeParabolicRectangle::Intersect(const Ray& objectRay, double *tHit, DifferentialGeometry *dg) const { double focus = focusLength.getValue(); double wX = widthX.getValue(); double wZ = widthZ.getValue(); // Compute quadratic coefficients double A = objectRay.direction().x * objectRay.direction().x + objectRay.direction().z * objectRay.direction().z; double B = 2.0 * ( objectRay.direction().x * objectRay.origin.x + objectRay.direction().z * objectRay.origin.z - 2 * focus * objectRay.direction().y ); double C = objectRay.origin.x * objectRay.origin.x + objectRay.origin.z * objectRay.origin.z - 4 * focus * objectRay.origin.y; // Solve quadratic equation for _t_ values double t0, t1; if( !gf::Quadratic( A, B, C, &t0, &t1 ) ) return false; // Compute intersection distance along ray if( t0 > objectRay.maxt || t1 < objectRay.mint ) return false; double thit = ( t0 > objectRay.mint )? t0 : t1 ; if( thit > objectRay.maxt ) return false; //Evaluate Tolerance double tol = 0.00001; //Compute possible hit position Point3D hitPoint = objectRay( thit ); // Test intersection against clipping parameters if( (thit - objectRay.mint) < tol || hitPoint.x < ( - wX / 2 ) || hitPoint.x > ( wX / 2 ) || hitPoint.z < ( - wZ / 2 ) || hitPoint.z > ( wZ / 2 ) ) { if ( thit == t1 ) return false; if ( t1 > objectRay.maxt ) return false; thit = t1; hitPoint = objectRay( thit ); if( (thit - objectRay.mint) < tol || hitPoint.x < ( - wX / 2 ) || hitPoint.x > ( wX / 2 ) || hitPoint.z < ( - wZ / 2 ) || hitPoint.z > ( wZ / 2 ) ) return false; } // Now check if the function is being called from IntersectP, // in which case the pointers tHit and dg are 0 if( ( tHit == 0 ) && ( dg == 0 ) ) return true; else if( ( tHit == 0 ) || ( dg == 0 ) ) gf::SevereError( "Function ParabolicCyl::Intersect(...) called with null pointers" ); /////////////////////////////////////////////////////////////////////////////////////// // Compute possible parabola hit position // Find parametric representation of paraboloid hit double u = ( hitPoint.x / wX ) + 0.5; double v = ( hitPoint.z / wZ ) + 0.5; Vector3D dpdu( wX, ( (-0.5 + u) * wX * wX ) / ( 2 * focus ), 0 ); Vector3D dpdv( 0.0, (( -0.5 + v) * wZ * wZ ) /( 2 * focus ), wZ ); // Compute parabaloid \dndu and \dndv Vector3D d2Pduu( 0.0, (wX * wX ) /( 2 * focus ), 0.0 ); Vector3D d2Pduv( 0.0, 0.0, 0.0 ); Vector3D d2Pdvv( 0.0, (wZ * wZ ) /( 2 * focus ), 0.0 ); // Compute coefficients for fundamental forms double E = DotProduct(dpdu, dpdu); double F = DotProduct(dpdu, dpdv); double G = DotProduct(dpdv, dpdv); NormalVector N = Normalize( NormalVector( CrossProduct( dpdu, dpdv ) ) ); double e = DotProduct(N, d2Pduu); double f = DotProduct(N, d2Pduv); double g = DotProduct(N, d2Pdvv); // Compute \dndu and \dndv from fundamental form coefficients double invEGF2 = 1.0 / (E*G - F*F); Vector3D dndu = (f*F - e*G) * invEGF2 * dpdu + (e*F - f*E) * invEGF2 * dpdv; Vector3D dndv = (g*F - f*G) * invEGF2 * dpdu + (f*F - g*E) * invEGF2 * dpdv; // Initialize _DifferentialGeometry_ from parametric information *dg = DifferentialGeometry(hitPoint, dpdu, dpdv, dndu, dndv, u, v, this); dg->shapeFrontSide = ( DotProduct( N, objectRay.direction() ) > 0 ) ? false : true; /////////////////////////////////////////////////////////////////////////////////////// // Update _tHit_ for quadric intersection *tHit = thit; return true; }
bool Cylinder::Intersect(const Ray &r, float *tHit, float *rayEpsilon, DifferentialGeometry *dg) const { float phi; Point phit; // Transform _Ray_ to object space Ray ray; (*WorldToObject)(r, &ray); // Compute quadratic cylinder coefficients float A = ray.d.x*ray.d.x + ray.d.y*ray.d.y; float B = 2 * (ray.d.x*ray.o.x + ray.d.y*ray.o.y); float C = ray.o.x*ray.o.x + ray.o.y*ray.o.y - radius*radius; // Solve quadratic equation for _t_ values float t0, t1; if (!Quadratic(A, B, C, &t0, &t1)) return false; // Compute intersection distance along ray if (t0 > ray.maxt || t1 < ray.mint) return false; float thit = t0; if (t0 < ray.mint) { thit = t1; if (thit > ray.maxt) return false; } // Compute cylinder hit point and $\phi$ phit = ray(thit); phi = atan2f(phit.y, phit.x); if (phi < 0.) phi += 2.f*M_PI; // Test cylinder intersection against clipping parameters if (phit.z < zmin || phit.z > zmax || phi > phiMax) { if (thit == t1) return false; thit = t1; if (t1 > ray.maxt) return false; // Compute cylinder hit point and $\phi$ phit = ray(thit); phi = atan2f(phit.y, phit.x); if (phi < 0.) phi += 2.f*M_PI; if (phit.z < zmin || phit.z > zmax || phi > phiMax) return false; } // Find parametric representation of cylinder hit float u = phi / phiMax; float v = (phit.z - zmin) / (zmax - zmin); // Compute cylinder $\dpdu$ and $\dpdv$ Vector dpdu(-phiMax * phit.y, phiMax * phit.x, 0); Vector dpdv(0, 0, zmax - zmin); // Compute cylinder $\dndu$ and $\dndv$ Vector d2Pduu = -phiMax * phiMax * Vector(phit.x, phit.y, 0); Vector d2Pduv(0, 0, 0), d2Pdvv(0, 0, 0); // Compute coefficients for fundamental forms float E = Dot(dpdu, dpdu); float F = Dot(dpdu, dpdv); float G = Dot(dpdv, dpdv); Vector N = Normalize(Cross(dpdu, dpdv)); float e = Dot(N, d2Pduu); float f = Dot(N, d2Pduv); float g = Dot(N, d2Pdvv); // Compute $\dndu$ and $\dndv$ from fundamental form coefficients float invEGF2 = 1.f / (E*G - F*F); Normal dndu = Normal((f*F - e*G) * invEGF2 * dpdu + (e*F - f*E) * invEGF2 * dpdv); Normal dndv = Normal((g*F - f*G) * invEGF2 * dpdu + (f*F - g*E) * invEGF2 * dpdv); // Initialize _DifferentialGeometry_ from parametric information const Transform &o2w = *ObjectToWorld; *dg = DifferentialGeometry(o2w(phit), o2w(dpdu), o2w(dpdv), o2w(dndu), o2w(dndv), u, v, this); // Update _tHit_ for quadric intersection *tHit = thit; // Compute _rayEpsilon_ for quadric intersection *rayEpsilon = 5e-4f * *tHit; return true; }
bool ShapeTroughCHC::Intersect(const Ray& objectRay, double *tHit, DifferentialGeometry *dg) const { double a = ( m_s - height.getValue() )/( cos( m_theta ) * 2 * m_eccentricity); double b = sqrt( ( m_eccentricity * m_eccentricity - 1 ) * a * a ); double angle = -( 0.5 * gc::Pi ) + m_theta; Transform hTransform( cos( angle ), -sin( angle ), 0.0, -r1.getValue() + a * m_eccentricity * sin( m_theta ), sin( angle ), cos( angle ), 0.0, - a * m_eccentricity * cos( m_theta ), 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ); Ray transformedRay = hTransform.GetInverse()( objectRay ); double A = ( transformedRay.direction().x * transformedRay.direction().x ) / ( a * a ) - ( transformedRay.direction().y * transformedRay.direction().y ) / ( b * b ); double B = 2.0 * ( ( ( transformedRay.origin.x * transformedRay.direction().x ) / ( a * a ) ) - ( ( transformedRay.origin.y * transformedRay.direction().y ) / ( b * b ) ) ); double C = ( ( transformedRay.origin.x * transformedRay.origin.x ) / ( a * a ) ) - ( ( transformedRay.origin.y * transformedRay.origin.y ) / ( b * b ) ) - 1; // Solve quadratic equation for _t_ values double t0, t1; if( !gf::Quadratic( A, B, C, &t0, &t1 ) ) return false; // Compute intersection distance along ray if( t0 > objectRay.maxt || t1 < objectRay.mint ) return false; double thit = ( t0 > objectRay.mint )? t0 : t1 ; if( thit > objectRay.maxt ) return false; //Evaluate Tolerance double tol = 0.00001; // Compute ShapeTroughCHC hit position and $\phi$ Point3D hitPoint = objectRay( thit ); // Test intersection against clipping parameters double m = ( lengthX2.getValue() / 2- lengthX1.getValue() / 2 ) / ( p1.getValue() - r1.getValue() ); double zmax = ( lengthX1.getValue() / 2 ) + m * ( hitPoint.x - r1.getValue() ); double zmin = - zmax; // Test intersection against clipping parameters if( (thit - objectRay.mint) < tol || hitPoint.x < r1.getValue() || hitPoint.x > p1.getValue() || hitPoint.y < 0.0 || hitPoint.y > height.getValue() || hitPoint.z < zmin || hitPoint.z > zmax ) { if ( thit == t1 ) return false; if ( t1 > objectRay.maxt ) return false; thit = t1; // Compute ShapeSphere hit position and $\phi$ hitPoint = objectRay( thit ); zmax = ( lengthX1.getValue() / 2 ) + m * ( hitPoint.x - r1.getValue() ); zmin = - zmax; if( (thit - objectRay.mint) < tol || hitPoint.x < r1.getValue() || hitPoint.x > p1.getValue() || hitPoint.y < 0.0 || hitPoint.y > height.getValue() || hitPoint.z < zmin || hitPoint.z > zmax ) return false; } // Find parametric representation of CHC concentrator hit double sup = m_theta + 0.5* gc::Pi; double inf = m_theta + m_phi; double alpha; bool isAlpha = findRoot( fPart, hitPoint.x, m_eccentricity, r1.getValue(), m_theta, inf, sup, 0.5*( sup-inf), 500, &alpha ); if( !isAlpha )return false; double u = ( alpha - inf ) / ( sup - inf ); zmax = (lengthX1.getValue() / 2 ) + m* ( hitPoint.x - r1.getValue() ); double v = ( ( hitPoint.z / zmax ) + 1 )/ 2; // Compute \dpdu and \dpdv Vector3D dpdu = GetDPDU( u, v ); Vector3D dpdv = GetDPDV( u, v ); // Compute cylinder \dndu and \dndv //Not yet implemented Vector3D d2Pduu( 0.0, 0.0, 0.0 ); Vector3D d2Pduv( 0.0, 0.0, 0.0 ); Vector3D d2Pdvv( 0.0, 0.0, 0.0 ); // Compute coefficients for fundamental forms double E = DotProduct( dpdu, dpdu ); double F = DotProduct( dpdu, dpdv ); double G = DotProduct( dpdv, dpdv ); Vector3D N = Normalize( CrossProduct( dpdu, dpdv ) ); double e = DotProduct( N, d2Pduu ); double f = DotProduct( N, d2Pduv ); double g = DotProduct( N, d2Pdvv ); // Compute \dndu and \dndv from fundamental form coefficients double invEGF2 = 1.0 / (E*G - F*F); Vector3D dndu = (f*F - e*G) * invEGF2 * dpdu + (e*F - f*E) * invEGF2 * dpdv; Vector3D dndv = (g*F - f*G) * invEGF2 * dpdu + (f*F - g*E) * invEGF2 * dpdv; // Initialize _DifferentialGeometry_ from parametric information *dg = DifferentialGeometry( hitPoint , dpdu, dpdv, dndu, dndv, u, v, this ); // Update _tHit_ for quadric intersection *tHit = thit; dg->shapeFrontSide = ( DotProduct( N, objectRay.direction() ) > 0 ) ? false : true; return true; }