Ejemplo n.º 1
0
    def __init__(self):
        """Default constructor for Intersection."""
        self.dg = DifferentialGeometry()

        self.primitive = None

        self.world_to_object = Transform()
        self.object_to_world = Transform()

        self.shape_id = 0
        self.primitive_id = 0

        self.ray_epsilon = 0.0
Ejemplo n.º 2
0
class Intersection(object):

    """Class describing an intersection of a Primitive."""

    def __init__(self):
        """Default constructor for Intersection."""
        self.dg = DifferentialGeometry()

        self.primitive = None

        self.world_to_object = Transform()
        self.object_to_world = Transform()
        
        self.shape_id = 0
        self.primitive_id = 0

        self.ray_epsilon = 0.0

    def get_bsdf(self, ray):
        """Compute the BSDF."""
        if self.primitive is None:
            logger.error("Intersect.get_bsdf() called with no primitive.")
            return 0.0
        self.dg.compute_differentials(ray)
        bsdf = self.primitive.get_bsdf(self.dg, self.object_to_world)
        return bsdf

    def get_bssrdf(self, ray):
        """Compute the BSSRDF."""
        if self.primitive is None:
            logger.error("Intersect.get_bssrddf() called with no primitive.")
            return 0.0
        self.dg.compute_differentials(ray)
        bssrdf = self.primitive.get_bssrdf(self.dg, self.object_to_world)
        return bssrdf

    def Le(self, w):
        """Return the light emitted by the object."""
        if self.primitive is None:
            logger.error("Intersect.Le() called with no primitive.")
            return Spectrum(0.0)
        area = self.primitive.get_area_light()
        if area:
            return area.L(self.dg.p, self.dg.nn, w)
        else:
            return Spectrum(0.0)

    def __str__(self):
        """Return a string describing the intersection."""
        return "Intersection (ids=%d/%d, prim='%s', dg='%s')" % \
               (self.shape_id, self.primitive_id, self.primitive, self.dg)
Ejemplo n.º 3
0
class Intersection(object):
    """Class describing an intersection of a Primitive."""
    def __init__(self):
        """Default constructor for Intersection."""
        self.dg = DifferentialGeometry()

        self.primitive = None

        self.world_to_object = Transform()
        self.object_to_world = Transform()

        self.shape_id = 0
        self.primitive_id = 0

        self.ray_epsilon = 0.0

    def get_bsdf(self, ray):
        """Compute the BSDF."""
        if self.primitive is None:
            logger.error("Intersect.get_bsdf() called with no primitive.")
            return 0.0
        self.dg.compute_differentials(ray)
        bsdf = self.primitive.get_bsdf(self.dg, self.object_to_world)
        return bsdf

    def get_bssrdf(self, ray):
        """Compute the BSSRDF."""
        if self.primitive is None:
            logger.error("Intersect.get_bssrddf() called with no primitive.")
            return 0.0
        self.dg.compute_differentials(ray)
        bssrdf = self.primitive.get_bssrdf(self.dg, self.object_to_world)
        return bssrdf

    def Le(self, w):
        """Return the light emitted by the object."""
        if self.primitive is None:
            logger.error("Intersect.Le() called with no primitive.")
            return Spectrum(0.0)
        area = self.primitive.get_area_light()
        if area:
            return area.L(self.dg.p, self.dg.nn, w)
        else:
            return Spectrum(0.0)

    def __str__(self):
        """Return a string describing the intersection."""
        return "Intersection (ids=%d/%d, prim='%s', dg='%s')" % \
               (self.shape_id, self.primitive_id, self.primitive, self.dg)
Ejemplo n.º 4
0
    def __init__(self):
        """Default constructor for Intersection."""
        self.dg = DifferentialGeometry()

        self.primitive = None

        self.world_to_object = Transform()
        self.object_to_world = Transform()
        
        self.shape_id = 0
        self.primitive_id = 0

        self.ray_epsilon = 0.0
Ejemplo n.º 5
0
    def intersect(self, r):
        """Intersect the ray with the shape."""
        # Transform _Ray_ to object space
        ray = self.world_to_object(r)

        # Compute quadratic sphere coefficients
        A = ray.d.x * ray.d.x + ray.d.y * ray.d.y + ray.d.z * ray.d.z
        B = 2 * (ray.d.x * ray.o.x + ray.d.y * ray.o.y + ray.d.z * ray.o.z)
        C = ray.o.x*ray.o.x + ray.o.y*ray.o.y + \
                  ray.o.z*ray.o.z - self.radius*self.radius

        # Solve quadratic equation for _t_ values
        found, t0, t1 = quadratic(A, B, C)
        if not found:
            return False, float('inf'), 0.0, None

        # Compute intersection distance along ray
        if (t0 > ray.maxt or t1 < ray.mint):
            return False, float('inf'), 0.0, None
        t_hit = t0
        if (t0 < ray.mint):
            t_hit = t1
            if (t_hit > ray.maxt):
                return False, float('inf'), 0.0, None

        # Compute sphere hit position and $\phi$
        phi_t = ray(t_hit)
        if (phi_t.x == 0.0 and phi_t.y == 0.0):
            phi_t.x = 1e-5 * self.radius
        phi = math.atan2(phi_t.y, phi_t.x)
        if (phi < 0.0):
            phi += 2.0 * math.pi

        # Test sphere intersection against clipping parameters
        if ((self.z_min > -self.radius and phi_t.z < self.z_min) or \
            (self.z_max <  self.radius and phi_t.z > self.z_max) or \
            phi > self.phi_max):
            if (t_hit == t1):
                return False, float('inf'), 0.0, None
            if (t1 > ray.maxt):
                return False, float('inf'), 0.0, None
            t_hit = t1
            # Compute sphere hit position and $\phi$
            phi_t = ray(t_hit)
            if (phi_t.x == 0.0 and phi_t.y == 0.0):
                phi_t.x = 1e-5 * self.radius
            phi = math.atan2(phi_t.y, phi_t.x)
            if (phi < 0.0):
                phi += 2.0 * math.pi
            if ((self.z_min > -self.radius and phi_t.z < self.z_min) or \
                (self.z_max <  self.radius and phi_t.z > self.z_max) or \
                phi > self.phi_max):
                return False, float('inf'), 0.0, None

        # Find parametric representation of sphere hit
        u = phi / self.phi_max
        theta = math.acos(clamp(phi_t.z / self.radius, -1.0, 1.0))
        v = (theta - self.theta_min) / (self.theta_max - self.theta_min)

        # Compute sphere $\dpdu$ and $\dpdv$
        zradius = math.sqrt(phi_t.x * phi_t.x + phi_t.y * phi_t.y)
        inv_z_radius = 1.0 / zradius
        cos_phi = phi_t.x * inv_z_radius
        sin_phi = phi_t.y * inv_z_radius
        dpdu = Vector(-self.phi_max * phi_t.y, self.phi_max * phi_t.x, 0)
        dpdv = (self.theta_max-self.theta_min) * \
               Vector(phi_t.z * cos_phi,
                      phi_t.z * sin_phi,
                      -self.radius * math.sin(theta))

        # Compute sphere $\dndu$ and $\dndv$
        d2Pduu = -self.phi_max * self.phi_max * Vector(phi_t.x, phi_t.y, 0)
        d2Pduv = (self.theta_max - self.theta_min) * phi_t.z * self.phi_max * \
                 Vector(-sin_phi, cos_phi, 0.0)
        d2Pdvv = -(self.theta_max - self.theta_min) * \
                 (self.theta_max - self.theta_min) * \
                 Vector(phi_t.x, phi_t.y, phi_t.z)

        # Compute coefficients for fundamental forms
        E = dot(dpdu, dpdu)
        F = dot(dpdu, dpdv)
        G = dot(dpdv, dpdv)
        N = normalize(cross(dpdu, dpdv))
        e = dot(N, d2Pduu)
        f = dot(N, d2Pduv)
        g = dot(N, d2Pdvv)

        # Compute $\dndu$ and $\dndv$ from fundamental form coefficients
        invEGF2 = 1.0 / (E * G - F * F)
        dndu = Normal.from_vector((f*F - e*G) * invEGF2 * dpdu + \
                                  (e*F - f*E) * invEGF2 * dpdv)
        dndv = Normal.from_vector((g*F - f*G) * invEGF2 * dpdu + \
                                  (f*F - g*E) * invEGF2 * dpdv)

        # Initialize _DifferentialGeometry_ from parametric information
        o2w = self.object_to_world
        dg = DifferentialGeometry.from_intersection(o2w(phi_t), o2w(dpdu),
                                                    o2w(dpdv), o2w(dndu),
                                                    o2w(dndv), u, v, self)

        # Compute _rayEpsilon_ for quadric intersection
        ray_epsilon = 5e-4 * t_hit
        return True, t_hit, ray_epsilon, dg
Ejemplo n.º 6
0
    def intersect(self, r):
        """Intersect the ray with the shape."""
        # Transform _Ray_ to object space
        ray = self.world_to_object(r)

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

        # Solve quadratic equation for _t_ values
        found, t0, t1 = quadratic(A, B, C)
        if not found:
            return False, float("inf"), 0.0, None

        # Compute intersection distance along ray
        if t0 > ray.maxt or t1 < ray.mint:
            return False, float("inf"), 0.0, None
        t_hit = t0
        if t0 < ray.mint:
            t_hit = t1
            if t_hit > ray.maxt:
                return False, float("inf"), 0.0, None

        # Compute sphere hit position and $\phi$
        phi_t = ray(t_hit)
        if phi_t.x == 0.0 and phi_t.y == 0.0:
            phi_t.x = 1e-5 * self.radius
        phi = math.atan2(phi_t.y, phi_t.x)
        if phi < 0.0:
            phi += 2.0 * math.pi

        # Test sphere intersection against clipping parameters
        if (
            (self.z_min > -self.radius and phi_t.z < self.z_min)
            or (self.z_max < self.radius and phi_t.z > self.z_max)
            or phi > self.phi_max
        ):
            if t_hit == t1:
                return False, float("inf"), 0.0, None
            if t1 > ray.maxt:
                return False, float("inf"), 0.0, None
            t_hit = t1
            # Compute sphere hit position and $\phi$
            phi_t = ray(t_hit)
            if phi_t.x == 0.0 and phi_t.y == 0.0:
                phi_t.x = 1e-5 * self.radius
            phi = math.atan2(phi_t.y, phi_t.x)
            if phi < 0.0:
                phi += 2.0 * math.pi
            if (
                (self.z_min > -self.radius and phi_t.z < self.z_min)
                or (self.z_max < self.radius and phi_t.z > self.z_max)
                or phi > self.phi_max
            ):
                return False, float("inf"), 0.0, None

        # Find parametric representation of sphere hit
        u = phi / self.phi_max
        theta = math.acos(clamp(phi_t.z / self.radius, -1.0, 1.0))
        v = (theta - self.theta_min) / (self.theta_max - self.theta_min)

        # Compute sphere $\dpdu$ and $\dpdv$
        zradius = math.sqrt(phi_t.x * phi_t.x + phi_t.y * phi_t.y)
        inv_z_radius = 1.0 / zradius
        cos_phi = phi_t.x * inv_z_radius
        sin_phi = phi_t.y * inv_z_radius
        dpdu = Vector(-self.phi_max * phi_t.y, self.phi_max * phi_t.x, 0)
        dpdv = (self.theta_max - self.theta_min) * Vector(
            phi_t.z * cos_phi, phi_t.z * sin_phi, -self.radius * math.sin(theta)
        )

        # Compute sphere $\dndu$ and $\dndv$
        d2Pduu = -self.phi_max * self.phi_max * Vector(phi_t.x, phi_t.y, 0)
        d2Pduv = (self.theta_max - self.theta_min) * phi_t.z * self.phi_max * Vector(-sin_phi, cos_phi, 0.0)
        d2Pdvv = (
            -(self.theta_max - self.theta_min) * (self.theta_max - self.theta_min) * Vector(phi_t.x, phi_t.y, phi_t.z)
        )

        # Compute coefficients for fundamental forms
        E = dot(dpdu, dpdu)
        F = dot(dpdu, dpdv)
        G = dot(dpdv, dpdv)
        N = normalize(cross(dpdu, dpdv))
        e = dot(N, d2Pduu)
        f = dot(N, d2Pduv)
        g = dot(N, d2Pdvv)

        # Compute $\dndu$ and $\dndv$ from fundamental form coefficients
        invEGF2 = 1.0 / (E * G - F * F)
        dndu = Normal.from_vector((f * F - e * G) * invEGF2 * dpdu + (e * F - f * E) * invEGF2 * dpdv)
        dndv = Normal.from_vector((g * F - f * G) * invEGF2 * dpdu + (f * F - g * E) * invEGF2 * dpdv)

        # Initialize _DifferentialGeometry_ from parametric information
        o2w = self.object_to_world
        dg = DifferentialGeometry.from_intersection(o2w(phi_t), o2w(dpdu), o2w(dpdv), o2w(dndu), o2w(dndv), u, v, self)

        # Compute _rayEpsilon_ for quadric intersection
        ray_epsilon = 5e-4 * t_hit
        return True, t_hit, ray_epsilon, dg