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
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)
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
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