Пример #1
0
bool Disk::Intersect(const Ray &r, float *tHit, float *rayEpsilon,
                     DifferentialGeometry *dg) const {
    // Transform _Ray_ to object space
    Ray ray;
    (*WorldToObject)(r, &ray);

    // Compute plane intersection for disk
    if (fabsf(ray.d.z) < 1e-7) return false;
    float thit = (height - ray.o.z) / ray.d.z;
    if (thit < ray.mint || thit > ray.maxt)
        return false;

    // See if hit point is inside disk radii and $\phimax$
    Point phit = ray(thit);
    float dist2 = phit.x * phit.x + phit.y * phit.y;
    if (dist2 > radius * radius || dist2 < innerRadius * innerRadius)
        return false;

    // Test disk $\phi$ value against $\phimax$
    float phi = atan2f(phit.y, phit.x);
    if (phi < 0) phi += 2. * M_PI;
    if (phi > phiMax)
        return false;

    // Find parametric representation of disk hit
    float u = phi / phiMax;
    float v = 1.f - ((sqrtf(dist2)-innerRadius) /
                     (radius-innerRadius));
    Vector dpdu(-phiMax * phit.y, phiMax * phit.x, 0.);
    Vector dpdv(-phit.x / (1-v), -phit.y / (1-v), 0.);
    dpdu *= phiMax * INV_TWOPI;
    dpdv *= (radius - innerRadius) / radius;
    Normal dndu(0,0,0), dndv(0,0,0);

    // Initialize _DifferentialGeometry_ from parametric information
    *dg = DifferentialGeometry((*ObjectToWorld)(phit),
                               (*ObjectToWorld)(dpdu),
                               (*ObjectToWorld)(dpdv),
                               (*ObjectToWorld)(dndu),
                               (*ObjectToWorld)(dndv),
                               u, v, this);

    // Update _tHit_ for quadric intersection
    *tHit = thit;

    // Compute _rayEpsilon_ for quadric intersection
    *rayEpsilon = 5e-4f * *tHit;
    return true;
}
Пример #2
0
bool DistanceEstimator::Intersect(const Ray &r, float *tHit, float *rayEpsilon,
    DifferentialGeometry *dg) const {
  bool succeed = DoesIntersect(r, tHit);
  if (!succeed) return false;

  Ray ray;
  (*WorldToObject)(r, &ray);
  Point p = ray(*tHit);
  *rayEpsilon = DE_params.hitEpsilon * DE_params.rayEpsilonMultiplier;
  Vector n = CalculateNormal(p, DE_params.normalEpsilon);
  Vector DPDU, DPDV;
  CoordinateSystem(n, &DPDU, &DPDV);

  const Transform &o2w = *ObjectToWorld;
  *dg = DifferentialGeometry(o2w(p), o2w(DPDU), o2w(DPDV), Normal(), Normal(), 0, 0, this);
  return true;
}
Пример #3
0
bool Sphere::Intersect(const Ray &r, Float *distance, Float *rayEpsilon,
		DifferentialGeometry *dg) const {
	Ray ray;
	(*worldToLocal)(r, &ray);
	// Compute quadratic sphere coefficients
	Float A = ray.d.x * ray.d.x + ray.d.y * ray.d.y + ray.d.z * ray.d.z;
	Float B = 2 * (ray.d.x * ray.o.x + ray.d.y * ray.o.y + ray.d.z * ray.o.z);
	Float C = ray.o.x * ray.o.x + ray.o.y * ray.o.y + ray.o.z * ray.o.z
			- mRad * mRad;
	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;
	}

	//这里开始计算参数化变量

	//计算phi
	Point phit;
	Float phi;
	phit = ray(thit);
	if (phit.x == 0.f && phit.y == 0.f)
		phit.x = 1e-5f * mRad; //排除除零的情况
	phi = atan2f(phit.y, phit.x);
	if (phi < 0.)
		phi += 2.f * Pi; //保证phi在2PI之中

	//判断是否在Z坐标之间的裁剪空间中
	if ((mZMin > -mRad && phit.z < mZMin) || (mZMax < mRad && phit.z > mZMax)
			|| phi > mPhiMax) {
		if (thit == t1)
			return false;
		if (t1 > ray.maxT)
			return false;
		thit = t1;

		phit = ray(thit);
		if (phit.x == 0.f && phit.y == 0.f)
			phit.x = 1e-5f * mRad;
		phi = atan2f(phit.y, phit.x);
		if (phi < 0.)
			phi += 2.f * Pi;
		if ((mZMin > -mRad && phit.z < mZMin)
				|| (mZMax < mRad && phit.z > mZMax) || phi > mPhiMax)
			return false;
	}

	// Find parametric representation of sphere hit
	//寻找参数化的u和v
	Float u = phi / mPhiMax;
	Float theta = acosf(Clamp(phit.z / mRad, -1.f, 1.f));
	Float v = (theta - mThetaMin) / (mThetaMax - mThetaMin);

	// 计算偏导 偏导还不是很熟悉,所以这里照搬了PBRT的公式,详细公式可以查阅PBRT
	Float zradius = sqrtf(phit.x * phit.x + phit.y * phit.y);
	Float invzradius = 1.f / zradius;
	Float cosphi = phit.x * invzradius;
	Float sinphi = phit.y * invzradius;
	Vector3f dpdu(-mPhiMax * phit.y, mPhiMax * phit.x, 0);
	Vector3f dpdv = (mThetaMax - mThetaMin)
			* Vector3f(phit.z * cosphi, phit.z * sinphi, -mRad * sinf(theta));

	//计算法线的偏导
	Vector3f d2Pduu = -mPhiMax * mPhiMax * Vector3f(phit.x, phit.y, 0);
	Vector3f d2Pduv = (mThetaMax - mThetaMin) * phit.z * mPhiMax
			* Vector3f(-sinphi, cosphi, 0.);
	Vector3f d2Pdvv = -(mThetaMax - mThetaMin) * (mThetaMax - mThetaMin)
			* Vector3f(phit.x, phit.y, phit.z);

	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);

	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);

	const Transform &o2w = *localToWorld;

	*dg = DifferentialGeometry(o2w(phit), o2w(dpdu), o2w(dpdv), o2w(dndu),
			o2w(dndv), u, v, this);
	*distance = thit;
	*rayEpsilon = 5e-4f * *distance; //交点处的Float误差

	return true;
}
Пример #4
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;

}
Пример #5
0
// 1. -- intersection or not.
// 2. -- fill differentialGeometry
bool Sphere::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);

	// 1. -- intersection or not.

    // Compute quadratic sphere coefficients
    float A = ray.d.x*ray.d.x + ray.d.y*ray.d.y + ray.d.z*ray.d.z;
    float B = 2 * (ray.d.x*ray.o.x + ray.d.y*ray.o.y + ray.d.z*ray.o.z);
    float C = ray.o.x*ray.o.x + ray.o.y*ray.o.y +
              ray.o.z*ray.o.z - radius*radius;

    // Solve quadratic equation for _t_ values
    float t0, t1;
    if (!Quadratic(A, B, C, &t0, &t1))		// in pbrt.h: Find quadratic discriminant
        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 sphere hit position and $\phi$
    phit = ray(thit);
    if (phit.x == 0.f && phit.y == 0.f) phit.x = 1e-5f * radius;
    phi = atan2f(phit.y, phit.x);
    if (phi < 0.) phi += 2.f*M_PI;

    // Test sphere intersection against clipping parameters
    if ((zmin > -radius && phit.z < zmin) ||
        (zmax <  radius && phit.z > zmax) || phi > phiMax) {
        if (thit == t1) return false;
        if (t1 > ray.maxt) return false;
        thit = t1;
        // Compute sphere hit position and $\phi$
        phit = ray(thit);
        if (phit.x == 0.f && phit.y == 0.f) phit.x = 1e-5f * radius;
        phi = atan2f(phit.y, phit.x);
        if (phi < 0.) phi += 2.f*M_PI;
        if ((zmin > -radius && phit.z < zmin) ||
            (zmax <  radius && phit.z > zmax) || phi > phiMax)
            return false;
    }

	// 2. -- fill differentialGeometry

    // Find parametric representation of sphere hit
    float u = phi / phiMax;
    float theta = acosf(Clamp(phit.z / radius, -1.f, 1.f));
    float v = (theta - thetaMin) / (thetaMax - thetaMin);

    // Compute sphere $\dpdu$ and $\dpdv$
    float zradius = sqrtf(phit.x*phit.x + phit.y*phit.y);
    float invzradius = 1.f / zradius;
    float cosphi = phit.x * invzradius;
    float sinphi = phit.y * invzradius;
    Vector dpdu(-phiMax * phit.y, phiMax * phit.x, 0);
    Vector dpdv = (thetaMax-thetaMin) *
        Vector(phit.z * cosphi, phit.z * sinphi,
               -radius * sinf(theta));

    // Compute sphere $\dndu$ and $\dndv$
    Vector d2Pduu = -phiMax * phiMax * Vector(phit.x, phit.y, 0);
    Vector d2Pduv = (thetaMax - thetaMin) * phit.z * phiMax *
                    Vector(-sinphi, cosphi, 0.);
    Vector d2Pdvv = -(thetaMax - thetaMin) * (thetaMax - thetaMin) *
                    Vector(phit.x, phit.y, phit.z);

    // 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;
}
Пример #6
0
bool Cone::Intersect(const Ray &r, float *tHit, float *rayEpsilon,
        DifferentialGeometry *dg) const {
    float phi;
    pbrt::Point phit;
    // Transform _Ray_ to object space
    Ray ray;
    (*WorldToObject)(r, &ray);

    // Compute quadratic cone coefficients
    float k = radius / height;
    k = k*k;
    float A = ray.d.x * ray.d.x + ray.d.y * ray.d.y -
        k * ray.d.z * ray.d.z;
    float B = 2 * (ray.d.x * ray.o.x + ray.d.y * ray.o.y -
        k * ray.d.z * (ray.o.z-height) );
    float C = ray.o.x * ray.o.x + ray.o.y * ray.o.y -
        k * (ray.o.z -height) * (ray.o.z-height);

    // 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 cone inverse mapping
    phit = ray(thit);
    phi = atan2f(phit.y, phit.x);
    if (phi < 0.) phi += 2.f*M_PI;

    // Test cone intersection against clipping parameters
    if (phit.z < 0 || phit.z > height || phi > phiMax) {
        if (thit == t1) return false;
        thit = t1;
        if (t1 > ray.maxt) return false;
        // Compute cone inverse mapping
        phit = ray(thit);
        phi = atan2f(phit.y, phit.x);
        if (phi < 0.) phi += 2.f*M_PI;
        if (phit.z < 0 || phit.z > height || phi > phiMax)
            return false;
    }

    // Find parametric representation of cone hit
    float u = phi / phiMax;
    float v = phit.z / height;

    // Compute cone $\dpdu$ and $\dpdv$
    Vector dpdu(-phiMax * phit.y, phiMax * phit.x, 0);
    Vector dpdv(-phit.x / (1.f - v),
                -phit.y / (1.f - v), height);

    // Compute cone $\dndu$ and $\dndv$
    Vector d2Pduu = -phiMax * phiMax *
                    Vector(phit.x, phit.y, 0.);
    Vector d2Pduv = phiMax / (1.f - v) *
                    Vector(phit.y, -phit.x, 0.);
    Vector 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;
}
Пример #7
0
bool Hyperboloid::Intersect(const Ray &r, float *tHit,
        float *rayEpsilon, DifferentialGeometry *dg) const {
    float phi, v;
    Point phit;
    // Transform _Ray_ to object space
    Ray ray;
    (*WorldToObject)(r, &ray);

    // Compute quadratic hyperboloid coefficients
    float A = a*ray.d.x*ray.d.x +
              a*ray.d.y*ray.d.y -
              c*ray.d.z*ray.d.z;
    float B = 2.f * (a*ray.d.x*ray.o.x +
                     a*ray.d.y*ray.o.y -
                     c*ray.d.z*ray.o.z);
    float C = a*ray.o.x*ray.o.x +
              a*ray.o.y*ray.o.y -
              c*ray.o.z*ray.o.z - 1;

    // 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 hyperboloid inverse mapping
    phit = ray(thit);
    v = (phit.z - p1.z)/(p2.z - p1.z);
    Point pr = (1.f-v) * p1 + v * p2;
    phi = atan2f(pr.x*phit.y - phit.x*pr.y,
        phit.x*pr.x + phit.y*pr.y);
    if (phi < 0)
        phi += 2*M_PI;

    // Test hyperboloid 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 hyperboloid inverse mapping
        phit = ray(thit);
        v = (phit.z - p1.z)/(p2.z - p1.z);
        Point pr = (1.f-v) * p1 + v * p2;
        phi = atan2f(pr.x*phit.y - phit.x*pr.y,
            phit.x*pr.x + phit.y*pr.y);
        if (phi < 0)
            phi += 2*M_PI;
        if (phit.z < zmin || phit.z > zmax || phi > phiMax)
            return false;
    }

    // Compute parametric representation of hyperboloid hit
    float u = phi / phiMax;

    // Compute hyperboloid $\dpdu$ and $\dpdv$
    float cosphi = cosf(phi), sinphi = sinf(phi);
    Vector dpdu(-phiMax * phit.y, phiMax * phit.x, 0.);
    Vector dpdv((p2.x-p1.x) * cosphi - (p2.y-p1.y) * sinphi,
        (p2.x-p1.x) * sinphi + (p2.y-p1.y) * cosphi,
        p2.z-p1.z);

    // Compute hyperboloid $\dndu$ and $\dndv$
    Vector d2Pduu = -phiMax * phiMax *
                    Vector(phit.x, phit.y, 0);
    Vector d2Pduv = phiMax *
                    Vector(-dpdv.y, dpdv.x, 0.);
    Vector 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;
}
Пример #8
0
bool Rectangle::Intersect(const Ray &r, float *tHit, float *rayEpsilon,
                     DifferentialGeometry *dg) const {

    // Transform _Ray_ to object space
        Ray ray;
        (*WorldToObject)(r, &ray);

        // Compute plane intersection for disk
        // Checks if the plane is parallel to the ray or not
        // We can get the direction of the ray
        // If the Z component of the direction of the ray is zero
        // then, the ray is parallel to the plane and in such case
        // there is no intersection point between the ray and the plane.
        if (fabsf(ray.d.z) < 1e-7)
            return false;

        // Now, the direction of the ray is not parallel to the plane
        // We have to check if the intersection happens or not
        // We have to compute the parametric t where the ray intersects the plane
        // We want to find t such that the z-component of the ray intersects the plane
        // The ray "line" equation is l = l0 + (l1 - l0) * t
        // l1 - l0 will give us the distance between the two points on the plane
        // Then t is the ratio and in such case it should be between 0 and 1
        // Considering that the rectangle completely lies in the z plane
        /// distance = l1 - l0
        /// thit = (l - l0) / distance

        // But since we assume that the plane is located at height
        // Then, the point l is at height on the plane
        /// l = height
        float thit = (height - ray.o.z) / ray.d.z;

        // Then we check if the thit is between the ratio of 0 and 1 that is mapped
        // between ray.mint and ray.maxt, if not retrun false
        if (thit < ray.mint || thit > ray.maxt)
            return false;

        // Then we see if the point lies inside the disk or not
        // Substitute the thit in the ray equation to get hit point on the ray
        Point phit = ray(thit);

        // We have to make sure that the interesction lies inside the plane
        if (!(phit.x < x/2 && phit.x > -x/2 && phit.y < y/2 && phit.y > -y/2))
            return false;

        // Assuming that the plane is formed from the following 4 points
        // P0, P1, P2, P3
        //
        // p0 *---------------* p1
        //    |               |
        //    |               |
        //    |               |
        //    |       O       |
        //    |               |
        //    |               |
        //    |               |
        // p2 *---------------* p3  -> X
        //
        // P0 @ (-x/2, y/2)
        // P1 @ (x/2, y/2)
        // P2 @ (-x/2, -y/2)
        // P3 @ (x/2, -y/2)
        Point P0(-x/2, y/2, height), P1(x/2, y/2, height);
        Point P2(-x/2, -y/2, height), P3(x/2, -y/2, height);

        /// Now, we have to find the parametric form of the plane in terms of (u,v)
        /// Plane equation can be formed by at least 3 points P0, P1, P2
        /// P0 -> P1 (vector 1)
        /// P0 -> p2 (vector 2)
        /// An arbitrary point on the plane p is found in the following parametric form
        /// P = P0 + (P1 - P0) u + (P2 - P0) v
        /// Now we need to express two explicit equations of u and v
        /// So, we have to construct the system of equation that solves for u and v
        ///
        /// Since we have found the intersection point between the plane and the line
        /// we have to use it to formalize the system of equations that will be used
        /// to find the parametric form of the plane
        /// Plane equation is : P = P0 + (P1 - P0) u + (P2 - P0) v
        /// Ray equation is : l = l0 + (l1 - l0) * thit
        /// But l = P, then
        /// l0 + (l1 - l0) * thit = P0 + (P1 - P0) * u + (P2 - P0) * v
        /// l0 - P0 = (l0 - l1) * thit +  (P1 - P0) * u + (P2 - P0) * v
        /// MAPPING : l0 = ray.o
        /// [l0.x - P0.x] = [l0.x - l1.x P1.x - P0.x P2.x - P0.x] [t]
        /// [l0.y - P0.y] = [l0.y - l1.y P1.y - P0.y P2.y - P0.y] [u]
        /// [l0.z - P0.z] = [l0.z - l1.z P1.z - P0.z P2.z - P0.z] [v]
        ///
        /// Then, we should find the inverse of the matrix in order to
        /// solve for u,v and t for check

        // System AX = B
        float a11 = ray.o.x - 0;
        float a12 = P1.x - P0.x;
        float a13 = P2.x - P0.x;
        float a21 = ray.o.y - 0;
        float a22 = P1.y - P0.y;
        float a23 = P2.y - P0.y;
        float a31 = ray.o.y - height;
        float a32 = P1.z - P0.z;
        float a33 = P2.z - P0.z;

        float b1 = -7;
        float b2 = -2;
        float b3 = 14;

        float x1 = 0;
        float x2 = 0;
        float x3 = 0;

        Imath::M33f A(a11,a12,a13,a21,a22,a23,a31,a32,a33), AInverted;
        Imath::V3f X(x1, x2, x3);
        Imath::V3f B(b1,b2, b3);

        // This operation has been checked and working for getting
        // the correct inverse of the matrix A
        AInverted = A.invert(false);

        x1 =  AInverted[0][0] * B[0] +
                AInverted[0][1] * B[1] +
                AInverted[0][2] * B[2];

        x2 =  AInverted[1][0] * B[0] +
                AInverted[1][1] * B[1] +
                AInverted[1][2] * B[2];

        x3 =  AInverted[2][0] * B[0] +
                AInverted[2][1] * B[1] +
                AInverted[2][2] * B[2];

        /// Then we have u = something, and v = something
        ///
        /// Then we come for the derivatives, so we have to find the derivatives
        /// from the parametric forms defined above for the plane equations
        /// dpdu = (P1 - P0)
        /// dpdv = (P2 - P0)
        ///
        /// For the normal we have the always fixed direction in y
        /// So the derivative for the normal is zero
        /// dndu = (0, 0, 0) dndv = (0, 0, 0)
        ///
        /// Then we can construct the DifferentilGeometry and go ahead

        // Find parametric representation of disk hit
        float u = x2;
        float v = x3;

        Vector dpdu(P1.x - P0.x, P1.y - P0.y, P1.z - P0.z);
        Vector dpdv(P2.x - P0.x, P2.y - P0.y, P2.z - P0.z);
        Normal dndu(0,0,0), dndv(0,0,0);


        // 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;
}
Пример #9
0
bool Sphere::intersect(const Ray &ray, float *t_hit, float *ray_epsilon, DifferentialGeometry *diff_geo) const
{
	// Transform Ray to object space
	Ray w_ray;
	(*world_to_object)(ray, &w_ray);

	// Compute quadratic sphere coefficients
	float phi;
	Point phit;
	float A = w_ray.d.x * w_ray.d.x + w_ray.d.y * w_ray.d.y + w_ray.d.z * w_ray.d.z;
	float B = 2 * (w_ray.d.x * w_ray.o.x + w_ray.d.y * w_ray.o.y + w_ray.d.z * w_ray.o.z);
	float C = w_ray.o.x*w_ray.o.x + w_ray.o.y*w_ray.o.y + w_ray.o.z*w_ray.o.z - _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 > w_ray.maxt || t1 < w_ray.mint)
		return false;
	float thit = t0;
	if (t0 < w_ray.mint) {
		thit = t1;
		if (thit > w_ray.maxt) return false;
	}

	// Compute sphere hit position and phi
	phit = w_ray(thit);
	if (phit.x == 0.f && phit.y == 0.f) phit.x = 1e-5f * _radius;
	phi = atan2f(phit.y, phit.x);
	if (phi < 0.) phi += 2.f * M_PI;

	// Test sphere intersection against clipping parameters
	if ((_z_min > -_radius && phit.z < _z_min) ||
		(_z_max <  _radius && phit.z > _z_max) || phi > _phi_max) { // clip t0(t1)
		if (thit == t1) return false;
		if (t1 > w_ray.maxt) return false;
		thit = t1;
		// Compute sphere hit position and phi
		phit = w_ray(thit);
		if (phit.x == 0.f && phit.y == 0.f) phit.x = 1e-5f * _radius;
		phi = atan2f(phit.y, phit.x);
		if (phi < 0.) phi += 2.f * M_PI;
		if ((_z_min > -_radius && phit.z < _z_min) ||
			(_z_max <  _radius && phit.z > _z_max) || phi > _phi_max)	// clip t1
			return false;
	}
	// Find parametric representatio n of sphere hit
	float u = phi / _phi_max;
	float theta = acosf(clamp(phit.z / _radius, -1.f, 1.f));
	float v = (theta - _theta_min) / (_theta_max - _theta_min);

	float z_radius = sqrtf(phit.x * phit.x + phit.y * phit.y);
	float inv_z_radius = 1.f / z_radius;
	float cos_phi = phit.x * inv_z_radius;
	float sin_phi = phit.y * inv_z_radius;
	Vec3 dpdu(-_phi_max * phit.y, _phi_max * phit.x, 0);
	Vec3 dpdv = (_theta_max - _theta_min) *
		Vec3(phit.z * cos_phi, phit.z * sin_phi, _radius * sinf(theta));

	//auto d2Pduu = -_phi_max * _phi_max * Vec3(phit.x, phit.y, 0);
	//auto d2Pduv = (_theta_max - _theta_min) * phit.z * _phi_max * Vec3(-sin_phi, cos_phi, 0.f);
	//auto d2Pdvv = (_theta_max - _theta_min) * (_theta_max - _theta_min) * Vec3(phit.x, phit.y, phit.z);
	//Normal dndu, dndv;
	//calc_dndu_dndv(dpdu, dpdv, d2Pduu, d2Pduv, d2Pdvv, &dndu, &dndv);
	Normal dndu(dpdu);
	Normal dndv(dpdv);

	const auto &o2w = *object_to_world;
	*diff_geo = DifferentialGeometry(o2w(phit), o2w(dpdu), o2w(dpdv),
		o2w(dndu), o2w(dndv), u, v, this);
	*t_hit = thit;
	*ray_epsilon = 5e-4f * *t_hit;
	return true;
}
Пример #10
0
bool Triangle::Intersect(const Ray &ray, Float *distance, Float *rayEpsilon,
		DifferentialGeometry *dg) const {
	Point p1 = mMesh->p[mIndex[0]];
	Point p2 = mMesh->p[mIndex[1]];
	Point p3 = mMesh->p[mIndex[2]];
	//这里使用质心坐标来计算 详见PBRT公式
	Vector3f e1 = p2 - p1; //e1=p2-p1
	Vector3f e2 = p3 - p1; //e2=p3-p1
	Vector3f s1 = Cross(ray.d, e2); //s1=d x e2
	Float divisor = Dot(s1, e1);
	if (divisor == 0.0f)
		return false;
	Float invDivisor = 1.f / divisor; //1/(s1.e1)

	// 计算第一个质心坐标
	Vector3f s = ray.o - p1; //s = o - p1
	Float b1 = Dot(s, s1) * invDivisor; //b1 = (s.s1)/(s1.e1)
	if (b1 < 0. || b1 > 1.)
		return false;

	// 计算第二个质心坐标
	Vector3f s2 = Cross(s, e1); //s2 = s x e1
	Float b2 = Dot(ray.d, s2) * invDivisor; // b2 = (d.s2)/(s1.e1)
	if (b2 < 0. || b1 + b2 > 1.)
		return false;

	// 计算参数t
	Float t = Dot(e2, s2) * invDivisor;
	if (t < ray.minT || t > ray.maxT)
		return false;

	Vector3f dpdu, dpdv; //p在u和v上的偏导
	Float uvs[3][2];
	GetUVs(uvs);

	//计算p在u和v上的偏导
	Float du1 = uvs[0][0] - uvs[2][0];
	Float du2 = uvs[1][0] - uvs[2][0];
	Float dv1 = uvs[0][1] - uvs[2][1];
	Float dv2 = uvs[1][1] - uvs[2][1];
	Vector3f dp1 = p1 - p3, dp2 = p2 - p3;
	Float determinant = du1 * dv2 - dv1 * du2;
	if (determinant == 0.f) {
		//行列式为0
		CoordinateSystem(Normalize(Cross(e2, e1)), &dpdu, &dpdv);
	} else {
		Float invdet = 1.f / determinant;
		dpdu = (dv2 * dp1 - dv1 * dp2) * invdet;
		dpdv = (-du2 * dp1 + du1 * dp2) * invdet;
	}
	//这里是在计算参数坐标  用的也是质心坐标
	Float b0 = 1 - b1 - b2;
	Float tu = b0 * uvs[0][0] + b1 * uvs[1][0] + b2 * uvs[2][0];
	Float tv = b0 * uvs[0][1] + b1 * uvs[1][1] + b2 * uvs[2][1];

	*dg = DifferentialGeometry(ray(t), dpdu, dpdv, Normal(0, 0, 0),
			Normal(0, 0, 0), tu, tv, this);
	*distance = t;
	*rayEpsilon = 1e-3f * *distance;
	//cout<<"射中三角"<<endl;
	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;
}
Пример #12
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;

}
Пример #13
0
// copy shapes/tianglemesh.cpp -> bool Triangle::Intersect(const Ray &ray, float *tHit, float *rayEpsilon, DifferentialGeometry *dg) const
bool Heightfield2::triangleIntersect (const Ray &ray, float *tHit, float *rayEpsilon, 
									  DifferentialGeometry *dg, Point triangle[]) const {
	const Point p1 = (*ObjectToWorld)(triangle[0]);
    const Point p2 = (*ObjectToWorld)(triangle[1]);
    const Point p3 = (*ObjectToWorld)(triangle[2]);
	Vector e1 = p2 - p1;
    Vector e2 = p3 - p1;
    Vector s1 = Cross(ray.d, e2);
    float divisor = Dot(s1, e1);
    
    if (divisor == 0.)
        return false;
    float invDivisor = 1.f / divisor;
	// Compute first barycentric coordinate
    Vector s = ray.o - p1;
    float b1 = Dot(s, s1) * invDivisor;
    if (b1 < 0. || b1 > 1.)
        return false;
    // Compute second barycentric coordinate
    Vector s2 = Cross(s, e1);
    float b2 = Dot(ray.d, s2) * invDivisor;
    if (b2 < 0. || b1 + b2 > 1.)
        return false;

    // Compute _t_ to intersection point
    float t = Dot(e2, s2) * invDivisor;
    if (t < ray.mint || t > ray.maxt)
        return false;
	
	// Compute triangle partial derivatives
    Vector dpdu, dpdv;
	
	// Compute deltas for triangle partial derivatives
    float du1 = triangle[0].x - triangle[2].x;
    float du2 = triangle[1].x - triangle[2].x;
    float dv1 = triangle[0].y - triangle[2].y;
    float dv2 = triangle[1].y - triangle[2].y;
    Vector dp1 = p1 - p3, dp2 = p2 - p3;
    float determinant = du1 * dv2 - dv1 * du2;
    if (determinant == 0.f) {
        // Handle zero determinant for triangle partial derivative matrix
        CoordinateSystem(Normalize(Cross(e2, e1)), &dpdu, &dpdv);
    }
    else {
        float invdet = 1.f / determinant;
        dpdu = ( dv2 * dp1 - dv1 * dp2) * invdet;
        dpdv = (-du2 * dp1 + du1 * dp2) * invdet;
    }

	// Interpolate $(u,v)$ triangle parametric coordinates
    float b0 = 1 - b1 - b2;
    float tu = b0*triangle[0].x + b1*triangle[1].x + b2*triangle[2].x;
    float tv = b0*triangle[0].y + b1*triangle[1].y + b2*triangle[2].y;

    // Fill in _DifferentialGeometry_ from triangle hit
    *dg = DifferentialGeometry(ray(t), dpdu, dpdv,
                               Normal(0,0,0), Normal(0,0,0),
                               tu, tv, this);
	
	*tHit = t;
    *rayEpsilon = 1e-3f * *tHit;
	return true;
}
Пример #14
0
void Heightfield2::GetShadingGeometry(const Transform &obj2world, const DifferentialGeometry &dg, DifferentialGeometry *dgShading) const {
    // Initialize _Triangle_ shading geometry with _n_ and _s_

    // *dgShading = dg;
    // return;

    Point p = Point(dg.u, dg.v, 0);
    int x = posToVoxel(p, 0);
    int y = posToVoxel(p, 1);
    int index1 = x + y*nx;
    int index2, index3;

    const Point &p1o = point[index1];
    if((dg.u-p1o.x)*width[1] > (dg.v-p1o.y)*width[0]){
        index2 = x+1 + y*nx;
        index3 = x+1 + (y+1)*nx;
    }else{
        index2 = x+1 + (y+1)*nx;
        index3 = x + (y+1)*nx;
    }
    const Point &p2o = point[index2];
    const Point &p3o = point[index3];
    const Normal &normal0 = normal[index1];
    const Normal &normal1 = normal[index2];
    const Normal &normal2 = normal[index3];

    // Compute barycentric coordinates for point
    float b[3];

    // Initialize _A_ and _C_ matrices for barycentrics
    float A[2][2] =
        { { p2o.x - p1o.x, p3o.x - p1o.x },
          { p2o.y - p1o.y, p3o.y - p1o.y } };
    float C[2] = { dg.u - p1o.x, dg.v - p1o.y };
    if (!SolveLinearSystem2x2(A, C, &b[1], &b[2])) {
        // Handle degenerate parametric mapping
        b[0] = b[1] = b[2] = 1.f/3.f;
    }
    else
        b[0] = 1.f - b[1] - b[2];

    // Use _n_ and _s_ to compute shading tangents for triangle, _ss_ and _ts_
    Normal ns;
    Vector ss, ts;
    ns = Normalize(obj2world(b[0] * normal0 + b[1] * normal1 + b[2] * normal2));
    ss = Normalize(dg.dpdu);
    
    ts = Cross(ss, ns);
    if (ts.LengthSquared() > 0.f) {
        ts = Normalize(ts);
        ss = Cross(ts, ns);
    }
    else
        CoordinateSystem((Vector)ns, &ss, &ts);
    Normal dndu, dndv;

    // Compute $\dndu$ and $\dndv$ for triangle shading geometry
    // Compute deltas for triangle partial derivatives of normal
    float du1 = p1o.x - p3o.x;
    float du2 = p2o.x - p3o.x;
    float dv1 = p1o.y - p3o.y;
    float dv2 = p2o.y - p3o.y;
    Normal dn1 = normal0 - normal2;
    Normal dn2 = normal1 - normal2;
    float determinant = du1 * dv2 - dv1 * du2;
    if (determinant == 0.f)
        dndu = dndv = Normal(0,0,0);
    else {
        float invdet = 1.f / determinant;
        dndu = ( dv2 * dn1 - dv1 * dn2) * invdet;
        dndv = (-du2 * dn1 + du1 * dn2) * invdet;
    }

    *dgShading = DifferentialGeometry(dg.p, ss, ts, obj2world(dndu), obj2world(dndv), dg.u, dg.v, dg.shape);
    dgShading->dudx = dg.dudx;  dgShading->dvdx = dg.dvdx;
    dgShading->dudy = dg.dudy;  dgShading->dvdy = dg.dvdy;
    dgShading->dpdx = dg.dpdx;  dgShading->dpdy = dg.dpdy;
}
Пример #15
0
bool Heightfield2::TriangleIntersect(const Ray &ray, float *tHit, float *rayEpsilon, DifferentialGeometry *dg, int index[]) const{
    PBRT_RAY_TRIANGLE_INTERSECTION_TEST(const_cast<Ray *>(&ray), const_cast<Triangle *>(this));

    // Get triangle vertices in _p1_, _p2_, and _p3_
    const Point &p1o = point[index[0]];
    const Point &p2o = point[index[1]];
    const Point &p3o = point[index[2]];
    const Point &p1 = (*ObjectToWorld)(p1o);
    const Point &p2 = (*ObjectToWorld)(p2o);
    const Point &p3 = (*ObjectToWorld)(p3o);
    Vector e1 = p2 - p1;
    Vector e2 = p3 - p1;
    Vector s1 = Cross(ray.d, e2);
    float divisor = Dot(s1, e1);
    
    if (divisor == 0.)
        return false;
    float invDivisor = 1.f / divisor;

    // Compute first barycentric coordinate
    Vector s = ray.o - p1;
    float b1 = Dot(s, s1) * invDivisor;
    if (b1 < 0. || b1 > 1.)
        return false;

    // Compute second barycentric coordinate
    Vector s2 = Cross(s, e1);
    float b2 = Dot(ray.d, s2) * invDivisor;
    if (b2 < 0. || b1 + b2 > 1.)
        return false;

    // Compute _t_ to intersection point
    float t = Dot(e2, s2) * invDivisor;
    if (t < ray.mint || t > ray.maxt)
        return false;

    // Compute triangle partial derivatives
    Vector dpdu, dpdv;

    // Compute deltas for triangle partial derivatives
    float du1 = p1o.x - p3o.x;
    float du2 = p2o.x - p3o.x;
    float dv1 = p1o.y - p3o.y;
    float dv2 = p2o.y - p3o.y;

    Vector dp1 = p1 - p3, dp2 = p2 - p3;
    float determinant = du1 * dv2 - dv1 * du2;
    if (determinant == 0.f) {
        // Handle zero determinant for triangle partial derivative matrix
        CoordinateSystem(Normalize(Cross(e2, e1)), &dpdu, &dpdv);
    }
    else {
        float invdet = 1.f / determinant;
        dpdu = ( dv2 * dp1 - dv1 * dp2) * invdet;
        dpdv = (-du2 * dp1 + du1 * dp2) * invdet;
    }

    // Interpolate $(u,v)$ triangle parametric coordinates
    float b0 = 1 - b1 - b2;
    float tu = b0*p1o.x + b1*p2o.x + b2*p3o.x;
    float tv = b0*p1o.y + b1*p2o.y + b2*p3o.y;

    // Fill in _DifferentialGeometry_ from triangle hit
    *dg = DifferentialGeometry(ray(t), dpdu, dpdv,
                               Normal(0,0,0), Normal(0,0,0),
                               tu, tv, this);
    *tHit = t;
    *rayEpsilon = 1e-3f * *tHit;
    ray.maxt = t;
    PBRT_RAY_TRIANGLE_INTERSECTION_HIT(const_cast<Ray *>(&ray), t);
    return true;
}
Пример #16
0
bool Triangle::Intersect(const Ray &ray, float *tHit, float *rayEpsilon,
                         DifferentialGeometry *dg) const {
    PBRT_RAY_TRIANGLE_INTERSECTION_TEST(const_cast<Ray *>(&ray), const_cast<Triangle *>(this));
    // Compute $\VEC{s}_1$

    // Get triangle vertices in _p1_, _p2_, and _p3_
    const Point &p1 = mesh->p[v[0]];
    const Point &p2 = mesh->p[v[1]];
    const Point &p3 = mesh->p[v[2]];
    Vector e1 = p2 - p1;
    Vector e2 = p3 - p1;
    Vector s1 = Cross(ray.d, e2);
    float divisor = Dot(s1, e1);
    
    if (divisor == 0.)
        return false;
    float invDivisor = 1.f / divisor;

    // Compute first barycentric coordinate
    Vector d = ray.o - p1;
    float b1 = Dot(d, s1) * invDivisor;
    if (b1 < 0. || b1 > 1.)
        return false;

    // Compute second barycentric coordinate
    Vector s2 = Cross(d, e1);
    float b2 = Dot(ray.d, s2) * invDivisor;
    if (b2 < 0. || b1 + b2 > 1.)
        return false;

    // Compute _t_ to intersection point
    float t = Dot(e2, s2) * invDivisor;
    if (t < ray.mint || t > ray.maxt)
        return false;

    // Compute triangle partial derivatives
    Vector dpdu, dpdv;
    float uvs[3][2];
    GetUVs(uvs);

    // Compute deltas for triangle partial derivatives
    float du1 = uvs[0][0] - uvs[2][0];
    float du2 = uvs[1][0] - uvs[2][0];
    float dv1 = uvs[0][1] - uvs[2][1];
    float dv2 = uvs[1][1] - uvs[2][1];
    Vector dp1 = p1 - p3, dp2 = p2 - p3;
    float determinant = du1 * dv2 - dv1 * du2;
    if (determinant == 0.f) {
        // Handle zero determinant for triangle partial derivative matrix
        CoordinateSystem(Normalize(Cross(e2, e1)), &dpdu, &dpdv);
    }
    else {
        float invdet = 1.f / determinant;
        dpdu = ( dv2 * dp1 - dv1 * dp2) * invdet;
        dpdv = (-du2 * dp1 + du1 * dp2) * invdet;
    }

    // Interpolate $(u,v)$ triangle parametric coordinates
    float b0 = 1 - b1 - b2;
    float tu = b0*uvs[0][0] + b1*uvs[1][0] + b2*uvs[2][0];
    float tv = b0*uvs[0][1] + b1*uvs[1][1] + b2*uvs[2][1];

    // Test intersection against alpha texture, if present
    if (ray.depth != -1) {
    if (mesh->alphaTexture) {
        DifferentialGeometry dgLocal(ray(t), dpdu, dpdv,
                                     Normal(0,0,0), Normal(0,0,0),
                                     tu, tv, this);
        if (mesh->alphaTexture->Evaluate(dgLocal) == 0.f)
            return false;
    }
    }

    // Fill in _DifferentialGeometry_ from triangle hit
    *dg = DifferentialGeometry(ray(t), dpdu, dpdv,
                               Normal(0,0,0), Normal(0,0,0),
                               tu, tv, this);
    *tHit = t;
    *rayEpsilon = 1e-3f * *tHit;
    PBRT_RAY_TRIANGLE_INTERSECTION_HIT(const_cast<Ray *>(&ray), t);
    return true;
}
Пример #17
0
void Triangle::GetShadingGeometry(const Transform &obj2world,
        const DifferentialGeometry &dg,
        DifferentialGeometry *dgShading) const {
    if (!mesh->n && !mesh->s) {
        *dgShading = dg;
        return;
    }
    // Initialize _Triangle_ shading geometry with _n_ and _s_

    // Compute barycentric coordinates for point
    float b[3];

    // Initialize _A_ and _C_ matrices for barycentrics
    float uv[3][2];
    GetUVs(uv);
    float A[2][2] =
        { { uv[1][0] - uv[0][0], uv[2][0] - uv[0][0] },
          { uv[1][1] - uv[0][1], uv[2][1] - uv[0][1] } };
    float C[2] = { dg.u - uv[0][0], dg.v - uv[0][1] };
    if (!SolveLinearSystem2x2(A, C, &b[1], &b[2])) {
        // Handle degenerate parametric mapping
        b[0] = b[1] = b[2] = 1.f/3.f;
    }
    else
        b[0] = 1.f - b[1] - b[2];

    // Use _n_ and _s_ to compute shading tangents for triangle, _ss_ and _ts_
    Normal ns;
    Vector ss, ts;
    if (mesh->n) ns = Normalize(obj2world(b[0] * mesh->n[v[0]] +
                                          b[1] * mesh->n[v[1]] +
                                          b[2] * mesh->n[v[2]]));
    else   ns = dg.nn;
    if (mesh->s) ss = Normalize(obj2world(b[0] * mesh->s[v[0]] +
                                          b[1] * mesh->s[v[1]] +
                                          b[2] * mesh->s[v[2]]));
    else   ss = Normalize(dg.dpdu);
    
    ts = Cross(ss, ns);
    if (ts.LengthSquared() > 0.f) {
        ts = Normalize(ts);
        ss = Cross(ts, ns);
    }
    else
        CoordinateSystem((Vector)ns, &ss, &ts);
    Normal dndu, dndv;

    // Compute $\dndu$ and $\dndv$ for triangle shading geometry
    if (mesh->n) {
        float uvs[3][2];
        GetUVs(uvs);
        // Compute deltas for triangle partial derivatives of normal
        float du1 = uvs[0][0] - uvs[2][0];
        float du2 = uvs[1][0] - uvs[2][0];
        float dv1 = uvs[0][1] - uvs[2][1];
        float dv2 = uvs[1][1] - uvs[2][1];
        Normal dn1 = mesh->n[v[0]] - mesh->n[v[2]];
        Normal dn2 = mesh->n[v[1]] - mesh->n[v[2]];
        float determinant = du1 * dv2 - dv1 * du2;
        if (determinant == 0.f)
            dndu = dndv = Normal(0,0,0);
        else {
            float invdet = 1.f / determinant;
            dndu = ( dv2 * dn1 - dv1 * dn2) * invdet;
            dndv = (-du2 * dn1 + du1 * dn2) * invdet;
        }
    }
    else
        dndu = dndv = Normal(0,0,0);
    *dgShading = DifferentialGeometry(dg.p, ss, ts,
        (*ObjectToWorld)(dndu), (*ObjectToWorld)(dndv),
        dg.u, dg.v, dg.shape);
    dgShading->dudx = dg.dudx;  dgShading->dvdx = dg.dvdx;
    dgShading->dudy = dg.dudy;  dgShading->dvdy = dg.dvdy;
    dgShading->dpdx = dg.dpdx;  dgShading->dpdy = dg.dpdy;
}
Пример #18
0
bool Sphere::Intersect( Ray const &ray, float *tHit, float *epsilon, DifferentialGeometry *geom ) const {
    Transform tf = Tform();
    Ray r = ray * Inverse( tf );

    float t;
    if( !Intersect( ray, &t ) )
        return false;

    // compute differential geometry
    Vec4 p = ray.Point( t );

    float x = p.X();
    float y = p.Y();
    float z = p.Z();

    if( x == 0.0f && z == 0.0f ) {
        // can't have both atan2 arguments be zero
        z = kEpsilon * m_radius;
    }
    float theta = atan2( p.X(), p.Z() );

    if( theta < 0.0f ) {
        // remap theta to [0, 2pi] to match sphere's definition
        theta += k2Pi;
    }

    float phi = Acos( Clamp( z / m_radius, -1.0f, 1.0f ) );

    // parameterize sphere hit
    float u = theta * kInv2Pi;
    float v = phi * kInvPi;

    float sTheta, cTheta;
    float sPhi, cPhi;
    SinCos( theta, &sTheta, &cTheta );
    SinCos( phi, &sPhi, &cPhi );

    Vec4 dpdu( k2Pi * z, 0.0f, -k2Pi * x, 0.0f );
    Vec4 dpdv( kPi * y * sTheta, -kPi * m_radius * sPhi, kPi * y * cTheta, 0.0f );
    Vec4 d2pdu2( -k2Pi * k2Pi * x, 0.0f, -k2Pi * k2Pi * z, 0.0f );
    Vec4 d2pduv( k2Pi * kPi * y * cTheta, 0.0f, -k2Pi * kPi * y * sTheta, 0.0f );
    Vec4 d2pdv2( -kPi * kPi * x, -kPi * kPi * y, -kPi * kPi * z, 0.0f );

    // change in normal is computed using Weingarten equations
    Scalar E = Dot( dpdu, dpdu );
    Scalar F = Dot( dpdu, dpdv );
    Scalar G = Dot( dpdv, dpdv );
    Vec4 N = Normalize( Cross(  dpdu, dpdv ) );
    Scalar e = Dot( N, d2pdu2 );
    Scalar f = Dot( N, d2pduv );
    Scalar g = Dot( N, d2pdv2 );

    Scalar h = 1.0f / ( E * G - F * F );
    Vec4 dndu = ( f * F - e * G ) * h * dpdu + ( e * F - f * E ) * h * dpdv;
    Vec4 dndv = ( g * F - f * G ) * h * dpdu + ( f * F - g * E ) * h * dpdv;

    *tHit = t;
    *epsilon = 5e-4f * t;

    // return world space differential geometry
    *geom = DifferentialGeometry( Handle(), p * tf, dpdu * tf, dpdv * tf, Normal( dndu ) * tf, Normal( dndv ) * tf, u, v );

    return true;
}