コード例 #1
0
ファイル: sphere.cpp プロジェクト: NextDesign1/pbrt-v3
bool Sphere::Sample(const Interaction &ref, const Point2f &sample,
                    Interaction *it) const {
    // Compute coordinate system for sphere sampling
    Point3f pCenter = (*ObjectToWorld)(Point3f(0, 0, 0));
    Point3f pOrigin =
        OffsetRayOrigin(ref.p, ref.pError, ref.n, pCenter - ref.p);
    Vector3f wc = Normalize(pCenter - ref.p);
    Vector3f wcX, wcY;
    CoordinateSystem(wc, &wcX, &wcY);

    // Sample uniformly on sphere if $\pt{}$ is inside it
    if (DistanceSquared(pOrigin, pCenter) <= 1.0001f * radius * radius)
        return Sample(sample, it);

    // Sample sphere uniformly inside subtended cone
    Float sinThetaMax2 = radius * radius / DistanceSquared(ref.p, pCenter);
    Float cosThetaMax =
        std::sqrt(std::max((Float)0., (Float)1. - sinThetaMax2));
    SurfaceInteraction isectSphere;
    Float tHit;
    Ray r = ref.SpawnRay(UniformSampleCone(sample, cosThetaMax, wcX, wcY, wc));
    if (!Intersect(r, &tHit, &isectSphere)) return false;
    *it = isectSphere;
    if (ReverseOrientation) it->n *= -1.f;
    return true;
}
コード例 #2
0
ファイル: sphere.cpp プロジェクト: yangjiaqian/pbrt-v3
Float Sphere::Pdf(const Interaction &ref, const Vector3f &wi) const {
    Point3f pCenter = (*ObjectToWorld)(Point3f(0, 0, 0));
    // Return uniform PDF if point is inside sphere
    Point3f pOrigin =
        OffsetRayOrigin(ref.p, ref.pError, ref.n, pCenter - ref.p);
    if (DistanceSquared(pOrigin, pCenter) <= radius * radius)
        return Shape::Pdf(ref, wi);

    // Compute general sphere PDF
    Float sinThetaMax2 = radius * radius / DistanceSquared(ref.p, pCenter);
    Float cosThetaMax = std::sqrt(std::max((Float)0, 1 - sinThetaMax2));
    return UniformConePdf(cosThetaMax);
}
コード例 #3
0
ファイル: sphere.cpp プロジェクト: yangjiaqian/pbrt-v3
Interaction Sphere::Sample(const Interaction &ref, const Point2f &u) const {
    // Compute coordinate system for sphere sampling
    Point3f pCenter = (*ObjectToWorld)(Point3f(0, 0, 0));
    Vector3f wc = Normalize(pCenter - ref.p);
    Vector3f wcX, wcY;
    CoordinateSystem(wc, &wcX, &wcY);

    // Sample uniformly on sphere if $\pt{}$ is inside it
    Point3f pOrigin =
        OffsetRayOrigin(ref.p, ref.pError, ref.n, pCenter - ref.p);
    if (DistanceSquared(pOrigin, pCenter) <= radius * radius) return Sample(u);

    // Sample sphere uniformly inside subtended cone

    // Compute $\theta$ and $\phi$ values for sample in cone
    Float sinThetaMax2 = radius * radius / DistanceSquared(ref.p, pCenter);
    Float cosThetaMax = std::sqrt(std::max((Float)0, 1 - sinThetaMax2));
    Float cosTheta = (1 - u[0]) + u[0] * cosThetaMax;
    Float sinTheta = std::sqrt(1 - cosTheta * cosTheta);
    Float phi = u[1] * 2 * Pi;

    // Compute angle $\alpha$ from center of sphere to sampled point on surface
    Float dc = Distance(ref.p, pCenter);
    Float ds = dc * cosTheta -
               std::sqrt(std::max(
                   (Float)0, radius * radius - dc * dc * sinTheta * sinTheta));
    Float cosAlpha = (dc * dc + radius * radius - ds * ds) / (2 * dc * radius);
    Float sinAlpha = std::sqrt(std::max((Float)0, 1 - cosAlpha * cosAlpha));

    // Compute surface normal and sampled point on sphere
    Vector3f nObj =
        SphericalDirection(sinAlpha, cosAlpha, phi, -wcX, -wcY, -wc);
    Point3f pObj = radius * Point3f(nObj.x, nObj.y, nObj.z);

    // Return _Interaction_ for sampled point on sphere
    Interaction it;

    // Reproject _pObj_ to sphere surface and compute _pObjError_
    pObj *= radius / Distance(pObj, Point3f(0, 0, 0));
    Vector3f pObjError = gamma(5) * Abs((Vector3f)pObj);
    it.p = (*ObjectToWorld)(pObj, pObjError, &it.pError);
    it.n = (*ObjectToWorld)(Normal3f(nObj));
    if (reverseOrientation) it.n *= -1.f;
    return it;
}