Exemplo n.º 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;
}
Exemplo n.º 2
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.º 3
0
bool Hyperboloid::Intersect(const Ray &r, Float *tHit,
                            SurfaceInteraction *isect) const {
    Float phi, v;
    Point3f pHit;
    // Transform _Ray_ to object space
    Vector3f oErr, dErr;
    Ray ray = (*WorldToObject)(r, &oErr, &dErr);

    // Compute quadratic hyperboloid 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 = ah * dx * dx + ah * dy * dy - ch * dz * dz;
    EFloat b = 2.f * (ah * dx * ox + ah * dy * oy - ch * dz * oz);
    EFloat c = ah * ox * ox + ah * oy * oy - ch * oz * oz - 1.f;

    // 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 (t0.LowerBound() <= 0) {
        tShapeHit = t1;
        if (tShapeHit.UpperBound() > ray.tMax) return false;
    }

    // Compute hyperboloid inverse mapping
    pHit = ray((Float)tShapeHit);
    v = (pHit.z - p1.z) / (p2.z - p1.z);
    Point3f pr = (1 - v) * p1 + v * p2;
    phi = std::atan2(pr.x * pHit.y - pHit.x * pr.y,
                     pHit.x * pr.x + pHit.y * pr.y);
    if (phi < 0) phi += 2 * Pi;

    // Test hyperboloid 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 hyperboloid inverse mapping
        pHit = ray((Float)tShapeHit);
        v = (pHit.z - p1.z) / (p2.z - p1.z);
        Point3f pr = (1 - v) * p1 + v * p2;
        phi = std::atan2(pr.x * pHit.y - pHit.x * pr.y,
                         pHit.x * pr.x + pHit.y * pr.y);
        if (phi < 0) phi += 2 * 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 = std::cos(phi), sinPhi = std::sin(phi);
    Vector3f dpdu(-phiMax * pHit.y, phiMax * pHit.x, 0.);
    Vector3f 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$
    Vector3f d2Pduu = -phiMax * phiMax * Vector3f(pHit.x, pHit.y, 0);
    Vector3f d2Pduv = phiMax * Vector3f(-dpdv.y, dpdv.x, 0.);
    Vector3f 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 hyperboloid intersection

    // Compute error bounds for intersection computed with ray equation
    EFloat px = ox + tShapeHit * dx;
    EFloat py = oy + tShapeHit * dy;
    EFloat pz = oz + tShapeHit * dz;
    Vector3f pError = Vector3f(px.GetAbsoluteError(), py.GetAbsoluteError(),
                               pz.GetAbsoluteError());

    // Initialize _SurfaceInteraction_ from parametric information
    *isect = (*ObjectToWorld)(SurfaceInteraction(pHit, pError, Point2f(u, v),
                                                 -ray.d, dpdu, dpdv, dndu, dndv,
                                                 ray.time, this));
    *tHit = (Float)tShapeHit;
    return true;
}
Exemplo n.º 4
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;
}
Exemplo n.º 5
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;
}
Exemplo n.º 6
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;
}
Exemplo n.º 7
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;
}
NormalVector ShapeParabolicRectangle::GetNormal( double u, double v ) const
{
	Vector3D dpdu( widthX.getValue(), ( (-0.5 + u) * widthX.getValue() *  widthX.getValue() )/(2 * focusLength.getValue()), 0 );
	Vector3D dpdv( 0.0, (( -0.5 + v) * widthZ.getValue() *  widthZ.getValue() ) /( 2 * focusLength.getValue() ), widthZ.getValue() );
	return Normalize( NormalVector( CrossProduct( dpdu, dpdv ) ) );
}
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;
}