def test_bbox_intersect(self): b = geo.BBox(geo.Point(1., 1., 1.), geo.Point(2., 2., 2.)) ray = geo.Ray(geo.Point(0., 0., 0.), geo.Vector(1., 1., 1.)) hit, t1, t2 = b.intersect_p(ray) assert hit assert_almost_eq(t1, 1.) assert_almost_eq(t2, 2.) # ambiguity in this case ray = geo.Ray(geo.Point(1. - EPS, 1. - EPS, 0.), geo.Vector(-EPS, -EPS, 1.)) hit, t1, t2 = b.intersect_p(ray) assert not hit assert_almost_eq(t1, 0.) assert_almost_eq(t2, 0.) ray = geo.Ray(geo.Point(1. - EPS, 1. - EPS, 1. - EPS), geo.Vector(-1., -1., -1.)) hit, t1, t2 = b.intersect_p(ray) assert not hit assert_almost_eq(t1, 0.) assert_almost_eq(t2, 0.) ray = geo.Ray(geo.Point(0., 0., 0.), geo.Vector(-1., -1., -1.)) hit, t1, t2 = b.intersect_p(ray) assert not hit assert_almost_eq(t1, 0.) assert_almost_eq(t2, 0.)
def test_call_ray(self, pnt, vec): ray = geo.Ray(pnt, vec) t = Transform() r = t(ray) assert isinstance(r, geo.Ray) assert r.o == ray.o assert r.d == ray.d
def test_ray_differential_from_ray(self, vec, pnt): r0 = geo.Ray(pnt, vec) r1 = geo.RayDifferential.from_ray(r0) assert r1.time == r0.time assert r1.depth == r0.depth assert not id(r1.o) == id(r0.o) assert not id(r1.d) == id(r0.d)
def sample_r(self, scene: 'Scene', ls: 'LightSample', u1: FLOAT, u2: FLOAT, time: FLOAT) -> ['geo.Ray', 'geo.Normal', FLOAT, 'Spectrum']: ray = geo.Ray(self.pos, mc.uniform_sample_sphere(ls.u_pos[0], ls.u_pos[1]), 0., np.inf, time) Ns = geo.Normal.fromVector(ray.d) pdf = mc.uniform_sphere_pdf() return [ray, Ns, pdf, self.intensity * self.__scale(ray.d)]
def sample_p(self, pnt: 'geo.Point', u1: FLOAT, u2: FLOAT) -> ['geo.Point', 'geo.Normal']: """ uniformly sample the sphere visible (of certain solid angle) to the point """ # compute coords for sampling ctr = self.o2w(geo.Point(0., 0., 0.)) wc = geo.normalize(ctr - pnt) _, wc_x, wc_y = geo.coordinate_system(wc) # sample uniformly if p is inside if pnt.sq_dist(ctr) - self.radius * self.radius < EPS: return self.sample(u1, u2) # sample inside subtended cone st_max_sq = self.radius * self.radius / pnt.sq_dist(ctr) ct_max = np.sqrt(max(0., 1. - st_max_sq)) from pytracer.montecarlo import uniform_sample_cone r = geo.Ray(pnt, uniform_sample_cone(u1, u2, ct_max, wc_x, wc_y, wc), EPS) hit, thit, _, _ = self.intersect(r) if not hit: thit = (ctr - pnt).dot(geo.normalize(r.d)) ps = r(thit) ns = geo.Normal.from_arr(geo.normalize(ps - ctr)) if self.ro: ns *= -1. return [ps, ns]
def generate_ray(self, sample: 'CameraSample') -> [FLOAT, 'geo.Ray']: """ Generate ray based on image sample. Returned ray direction is normalized """ # generate raster and camera samples Pras = geo.Point(sample.imageX, sample.imageY, 0.) Pcam = self.r2c(Pras) ray = geo.Ray(Pcam, geo.Vector(0., 0., 1.), 0., np.inf) # modify ray for dof if self.lens_rad > 0.: # sample point on lens from pytracer.montecarlo import concentric_sample_disk lens_u, lens_v = \ concentric_sample_disk(sample.lens_u, sample.lens_v) lens_u *= self.lens_rad lens_v *= self.lens_rad # compute point on focal plane ft = self.focal_dist / ray.d.z Pfoc = ray(ft) # update ray ray.o = geo.Point(lens_u, lens_v, 0.) ray.d = geo.normalize(Pfoc - ray.o) ray.time = util.lerp(sample.time, self.s_open, self.s_close) ray = self.c2w(ray) return [1., ray]
def set_ray(self, p: 'geo.Point', eps: FLOAT, w: 'geo.Vector', time: FLOAT): """ set_ray() The test is to indicate whether there is any object along a given direction. """ self.ray = geo.Ray(p, w, eps, np.inf, time=time)
def sample_r(self, scene: 'Scene', ls: 'LightSample', u1: FLOAT, u2: FLOAT, time: FLOAT) -> ['geo.Ray', 'geo.Normal', FLOAT, 'Spectrum']: v = mc.uniform_sample_cone(ls.u_pos[0], ls.u_pos[1], self.cos_width) ray = geo.Ray(self.pos, self.l2w(v), 0., np.inf, time) Ns = geo.Normal.fromVector(ray.d) pdf = mc.uniform_cone_pdf(self.cos_width) return [ray, Ns, pdf, self.intensity * self.__projection(ray.d)]
def set_segment(self, p1: 'geo.Point', eps1: FLOAT, p2: 'geo.Point', eps2: FLOAT, time: FLOAT): """ set_segment() The test is to be done within the given segment. """ dist = (p1 - p2).length() self.ray = geo.Ray(p1, (p2 - p1) / dist, eps1, dist * (1. - eps2), time=time)
def sample_r(self, scene: 'Scene', ls: 'LightSample', u1: FLOAT, u2: FLOAT, time: FLOAT) -> ['geo.Ray', 'geo.Normal', FLOAT, 'Spectrum']: """ Create a bounding disk and uniformly sample on it. """ org, Ns = self.shape_set.sample(ls) di = mc.uniform_sample_sphere(u1, u2) if di.dot(Ns) < 0.: di *= -1. ray = geo.Ray(org, di, EPS, np.inf, time) pdf = self.shape_set.pdf(org) * INV_2PI return [ray, Ns, pdf, self.l(org, Ns, di)]
def tau(self, r: 'geo.Ray', step_size: FLOAT, u: FLOAT) -> 'Spectrum': tau = Spectrum(0.) length = r.d.length() if length == 0.: return tau rn = geo.Ray(r.o, r.d / length, r.mint * length, r.maxt * length, r.time) hit, t0, t1 = self.intersect_p(rn) if not hit: return tau t0 += u * step_size while t0 < t1: tau += self.sigma_t(rn(t0), -rn.d, r.time) t0 += step_size return tau * step_size
def sample_r(self, scene: 'Scene', ls: 'LightSample', u1: FLOAT, u2: FLOAT, time: FLOAT) -> ['geo.Ray', 'geo.Normal', FLOAT, 'Spectrum']: """ Create a bounding disk and uniformly sample on it. """ # choose point on disk oriented towards light ctr, rad = scene.world_bound().bounding_sphere() _, v1, v2 = geo.coordinate_system(self.di) d1, d2 = mc.concentric_sample_disk(ls.u_pos[0], ls.u_pos[1]) pnt = ctr + rad * (d1 * v1 + d2 * v2) # set ray ray = geo.Ray(pnt + rad * self.di, -self.di, 0., np.inf, time) Ns = geo.Normal.fromVector(ray.d) pdf = 1. / (PI * rad * rad) return [ray, Ns, pdf, self.l]
def generate_ray(self, sample: 'CameraSample') -> [FLOAT, 'geo.Ray']: """ Generate ray based on image sample. Returned ray direction is normalized """ time = util.lerp(sample.time, self.s_open, self.s_close) # compute ray direction theta = np.pi * sample.imageY / self.film.yResolution phi = 2 * np.pi * sample.imageX / self.film.xResolution stheta = np.sin(theta) ray = self.c2w( geo.Ray( geo.Point(0., 0., 0.), geo.Vector(stheta * np.cos(phi), np.cos(theta), stheta * np.sin(phi)), 0., np.inf, time)) return [1., ray]
def sample_r(self, scene: 'Scene', ls: 'LightSample', u1: FLOAT, u2: FLOAT, time: FLOAT) -> ['geo.Ray', 'geo.Normal', FLOAT, 'Spectrum']: """ Create a bounding disk and uniformly sample on it. """ # find (u, v) sample coords in inf. light texture uv, pdf = self.dist.sample_cont(ls.u_pos[0], ls.u_pos[1]) if pdf == 0.: return [None, None, 0., Spectrum(0.)] theta = uv[1] * PI phi = uv[0] * 2. * PI ct = np.cos(theta) st = np.sin(theta) sp = np.sin(phi) cp = np.cos(phi) d = -self.l2w(geo.Vector(st * cp, st * sp, ct)) Ns = geo.Normal.fromVector(d) # choose point on disk oriented towards light ctr, rad = scene.world_bound().bounding_sphere() _, v1, v2 = geo.coordinate_system(self.di) d1, d2 = mc.concentric_sample_disk(ls.u_pos[0], ls.u_pos[1]) pnt = ctr + rad * (d1 * v1 + d2 * v2) # set ray ray = geo.Ray(pnt + rad * (-d), d, 0., np.inf, time) # compute pdf dir_pdf = pdf / (2. * PI * PI * st) area_pdf = 1. / (PI * rad * rad) pdf = dir_pdf * area_pdf if st == 0.: pdf == 0. return [ray, Ns, pdf, Spectrum.from_rgb(self.radMap.look_up([uv[0], uv[1]]), SpectrumType.ILLUMINANT)]
def test_ray_call(self, vec, pnt): ray = geo.Ray(pnt, vec) t = rng() p = ray(t) assert isinstance(pnt, geo.Point) assert p == pnt + vec * t
def test_ray_from_parent(self, vec, pnt): r0 = geo.Ray(pnt, vec) r1 = geo.Ray.from_parent(pnt, vec, r0) assert r1.time == r0.time assert r1.depth == r0.depth + 1
def generate_ray(self, sample: 'CameraSample') -> [FLOAT, 'geo.Ray']: p = geo.Point(sample.imageX, sample.imageY, 0.) pp = geo.Point(0., 0., self.focal) d = self.c2w.startTransform(pp - p) p = self.c2w.startTransform(p) return 1., geo.Ray(p, d)