Exemplo n.º 1
0
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;
}
Exemplo n.º 2
0
/*!
 * 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;
}
Exemplo n.º 4
0
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;
}
Exemplo n.º 5
0
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;

}