示例#1
0
bool NaiadFoamParticle::IntersectP(const Ray &rayInc) const {
    Matrix4x4 w2o_m;
    w2o_m.m[0][3] = -pos.x;
    w2o_m.m[1][3] = -pos.y;
    w2o_m.m[2][3] = -pos.z;
    Transform w2o = Transform(w2o_m);

    float phi;
    Point phit;
    // Transform _Ray_ to object space
    Ray ray;
    w2o(rayInc, &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 - r*r;

    // 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;
    }

    return true;
}
示例#2
0
文件: Sphere.cpp 项目: caomw/renderer
bool Sphere::intersect(const Ray& ray, RaySurfIntersection& res)const{
    res.shp = NULL;

    //Transform ray to object space
    const Ray rOb = w2o(ray);

    const Vector o = Vector(rOb.getOrigin().x, rOb.getOrigin().y, rOb.getOrigin().z);
    const Vector d = rOb.getDir();
    const float A = d.dot(d);
    const float B = 2.0f * (d.dot(o));
    const float C = o.dot(o) - (r * r);


    struct MathUtils::QuadraticEqnRes<float> slv =
        MathUtils::solveQuadratic<float>(A, B, C);
    float tHitFinal = 0.0f; //After the below code this will eventually be set to
    //the first hit point in front of the camera
    if(slv.solCount == 0){
        return false;
    }else if(slv.solCount == 1){
        tHitFinal = slv.sol1;
        if(tHitFinal < 0.0f){
            //No solutions in front of camera
            return false;
        }
    }else{ //2 solutions
        //Find smallest t value that is > 0.0f
        if(slv.sol1 < 0.0f && slv.sol2 < 0.0f){
            //No solutions in front of camera
            return false;
        }else{
            //At least one hit in front of camera
            slv.sol1 = slv.sol1 < 0.0f ? Constants::MAX_FLOAT_VAL : slv.sol1;
            slv.sol2 = slv.sol2 < 0.0f ? Constants::MAX_FLOAT_VAL : slv.sol2;
            tHitFinal = std::min<float>(slv.sol1, slv.sol2);
        }
    }

    //Make sure hit is in front of camera
    Assert(tHitFinal >= 0.0f);

    res.tHit = tHitFinal;
    res.locWS = ray(res.tHit);
    Vector normalVecAtHit = res.locWS - o2w(Point(0.0f,0.0f,0.0f));
    res.n = normalVecAtHit.getNormalized();
    res.shp = this;
    return true;
}
示例#3
0
bool NaiadFoamParticle::Intersect(const Ray &rayInc, float *tHit, float *rayEpsilon,
                                  DifferentialGeometry *dg) const {
    /*const float X0 = ray.o.x;
    const float Y0 = ray.o.y;
    const float Z0 = ray.o.z;

    const float Xd = ray.d.x;
    const float Yd = ray.d.y;
    const float Zd = ray.d.z;

    const float Xc = pos.x;
    const float Yc = pos.y;
    const float Zc = pos.z;

    const float B = 2.0f * (Xd * (X0 - Xc) + Yd * (Y0 - Yc) + Zd * (Z0 - Zc));
    const float C = (X0-Xc)*(X0-Xc) + (Y0-Yc)*(Y0-Yc) + (Z0-Zc)*(Z0-Zc) - r*r;

    const float discriminant = B*B - 4*C;
    if (discriminant < 0.0f)
        return false;
    const float t0 = (- B - sqrt(discriminant)) / 2.0f;
    const float t1 = (- B + sqrt(discriminant)) / 2.0f;
    if (t0 < 0 || t0 != t0) {
        return true;
    }*/

    Matrix4x4 w2o_m;
    w2o_m.m[0][3] = -pos.x;
    w2o_m.m[1][3] = -pos.y;
    w2o_m.m[2][3] = -pos.z;
    Transform w2o = Transform(w2o_m);

    const float thetaMin = -M_PI;
    const float thetaMax = 0;
    const float phiMax = 2.f*M_PI;

    float phi;
    Point phit;
    // Transform _Ray_ to object space
    Ray ray;
    w2o(rayInc, &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 - r*r;

    // 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 sphere hit position and $\phi$
    phit = ray(thit);
    rayInc.hitFoam = true;
    PerspectiveCamera * cam = PerspectiveCamera::cur_cam;
    Transform c2w;
    cam->CameraToWorld.Interpolate(0.f, &c2w);
    Transform w2c = Inverse(c2w);
    Transform c2s = cam->CameraToScreen;
    Transform s2r = cam->ScreenToRaster;

    Point cPos = w2c(phit);
    Point rPos = s2r(c2s(cPos));
    int x = (int)(rPos.x + 0.5);
    int y = (int)(rPos.y + 0.5);
    int w = cam->film->xResolution;
    int h = cam->film->yResolution;

    if (x > 0 && y > 0 && x < w && y < h) {
        rayInc.hitFoam = true;
        /*printf("%i %i %i %i\n", x, y, w ,h);
        std::cout << parent << std::endl;
        std::cout << parent->parent << std::endl;
        std::cout << parent->parent->foamPlane[0] << std::endl;
        std::cout << parent->parent->foamPlane.size() << std::endl;
        std::cout << x + y*w << std::endl;*/
        //std::cout << NaiadFoam::cur->FoamPlane().size() << std::endl;
        rayInc.alphaFoam = NaiadFoam::cur->FoamPlane()[x + y*w];
    }

    /*if (phit.x == 0.f && phit.y == 0.f) phit.x = 1e-5f * r;
    phi = atan2f(phit.y, phit.x);
    if (phi < 0.) phi += 2.f*M_PI;

    // Find parametric representation of sphere hit
    float u = phi / phiMax;
    float theta = acosf(Clamp(phit.z / r, -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,
               -r * 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);

    //std::cout << "Got here?" << std::endl;

    Matrix4x4 o2w_m;
    o2w_m.m[0][3] = pos.x;
    o2w_m.m[1][3] = pos.y;
    o2w_m.m[2][3] = pos.z;
    Transform o2w = Transform(o2w_m);

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

    dg->mult = 1.f;*/

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

    // Compute _rayEpsilon_ for quadric intersection
    //*rayEpsilon = 5e-4f * *tHit;
    return true;
}