示例#1
0
bool Disk::Intersect(const Ray &r, Float *tHit,
                     SurfaceInteraction *isect) const {
    // Transform _Ray_ to object space
    Vector3f oErr, dErr;
    Ray ray = (*WorldToObject)(r, &oErr, &dErr);

    // Compute plane intersection for disk

    // Reject disk intersections for rays parallel to the disk's plane
    if (ray.d.z == 0) return false;
    Float tShapeHit = (height - ray.o.z) / ray.d.z;
    if (tShapeHit <= 0 || tShapeHit >= ray.tMax) return false;

    // See if hit point is inside disk radii and $\phimax$
    Point3f pHit = ray(tShapeHit);
    Float dist2 = pHit.x * pHit.x + pHit.y * pHit.y;
    if (dist2 > radius * radius || dist2 < innerRadius * innerRadius)
        return false;

    // Refine disk intersection point
    pHit.z = height;

    // Test disk $\phi$ value against $\phimax$
    Float phi = std::atan2(pHit.y, pHit.x);
    if (phi < 0) phi += 2 * Pi;
    if (phi > phiMax) return false;

    // Find parametric representation of disk hit
    Float u = phi / phiMax;
    Float rHit = std::sqrt(dist2);
    Float oneMinusV = ((rHit - innerRadius) / (radius - innerRadius));
    Float v = 1 - oneMinusV;
    Vector3f dpdu(-phiMax * pHit.y, phiMax * pHit.x, 0.);
    Vector3f dpdv =
        Vector3f(pHit.x, pHit.y, 0.) * (innerRadius - radius) / rHit;
    Normal3f dndu(0, 0, 0), dndv(0, 0, 0);

    // Compute error bounds for disk intersection
    Vector3f pError(0., 0., 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;
}
示例#2
0
文件: disk.cpp 项目: sungsoo/pbrt-v2
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;
}
示例#3
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;
}
示例#4
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;
}