Ejemplo n.º 1
0
 def test_spherical(self, theta, phi):
     st = np.sin(theta)
     ct = np.cos(theta)
     v = geo.spherical_direction(st, ct, phi)
     theta_ret = geo.spherical_theta(v)
     phi_ret = geo.spherical_phi(v)
     assert_almost_eq(theta, theta_ret)
     assert_almost_eq(phi, phi_ret)
Ejemplo n.º 2
0
	def sample(self, u1: FLOAT, u2: FLOAT) -> ['geo.Point', 'geo.Normal']:
		"""
		account for partial sphere
		"""
		from pytracer.montecarlo import uniform_sample_sphere
		v = uniform_sample_sphere(u1, u2)

		phi = geo.spherical_theta(v) * self.phiMax * INV_2PI
		theta = self.thetaMin + geo.spherical_theta(v) * (self.thetaMax - self.thetaMin)

		v = geo.spherical_direction(np.sin(theta), np.cos(theta), phi) * self.radius
		v.z = self.zmin + v.z * (self.zmax - self.zmin)

		p = geo.Point.from_arr(v)
		Ns = geo.normalize(self.o2w(geo.Normal(p.x, p.y, p.z)))
		if self.ro:
			Ns *= -1.
		return [self.o2w(p), Ns]
Ejemplo n.º 3
0
def sample_hg(w: 'geo.Vector', g: FLOAT, u1: FLOAT, u2: FLOAT) -> 'geo.Vector':
    """
	sample_hg()

	Sampling from Henyey-Greestein
	phase function, i.e.,
	$$
	\cos(\theta) = \frac{1}{2g}\left(1 + g^2 - \left( \frac{1-g^2}{1-g+2g\zeta} \right) ^2 \right))
	$$
	"""
    if np.fabs(g) < EPS:
        ct = 1. - 2. * u1
    else:
        sqr = (1. - g * g) / (1. - g + 2. * g * u1)
        ct = (1. + g * g - sqr * sqr) / (2. * g)

    st = np.sqrt(max(0., 1 - ct * ct))
    phi = 2. * PI * u2
    _, v1, v2 = geo.coordinate_system(w)
    return geo.spherical_direction(st, ct, phi, v1, v2, w)
Ejemplo n.º 4
0
    def sample_f(self, wo: 'geo.Vector', u1: FLOAT,
                 u2: FLOAT) -> [FLOAT, 'geo.Vector']:
        # compute sampled half-angle vector
        ct = np.power(u1, 1. / (self.e + 1))
        st = np.sqrt(max(0., 1. - ct * ct))
        phi = u2 * 2. * PI
        wh = geo.spherical_direction(st, ct, phi)

        if wo.z * wh.z <= 0.:
            wh *= -1.

        # incident direction by reflection
        wi = -wo + 2. * wo.dot(wh) * wh

        # pdf
        pdf = ((self.e + 1.) * np.power(ct, self.e)) / \
              (2. * PI * 4. * wo.dot(wh))

        if wo.dot(wh) <= 0.:
            pdf = 0.

        return [pdf, wi]
Ejemplo n.º 5
0
    def sample_f(self, wo: 'geo.Vector', u1: FLOAT,
                 u2: FLOAT) -> [FLOAT, 'geo.Vector']:
        # sample from first quadrant and remap to hemisphere to sample w_h
        if u1 < .25:
            phi, ct = self.__sample_first_quad(4. * u1, u2)
        elif u1 < .5:
            u1 = 4. * (.5 - u1)
            phi, ct = self.__sample_first_quad(u1, u2)
            phi = PI - phi
        elif u1 < .75:
            u1 = 4. * (u1 - .5)
            phi, ct = self.__sample_first_quad(u1, u2)
            phi += PI
        else:
            u1 = 4. * (1. - u1)
            phi, ct = self.__sample_first_quad(u1, u2)
            phi = 2. * PI - phi

        st = np.sqrt(max(0., 1. - ct * ct))
        wh = geo.spherical_direction(st, ct, phi)
        if wo.z * wh.z <= 0.:
            wh *= -1.

        # incident direction by reflection
        wi = -wo + 2. * wo.dot(wh) * wh

        # compute pdf for w_i
        ct = abs_cos_theta(wh)
        ds = 1. - ct * ct
        if ds > 0. and wo.dot(wh) > 0.:
            return [(np.sqrt((self.ex + 1.) * (self.ey + 1.)) * INV_2PI * np.power(ct,
                                                                                   (
                                                                                   self.ex * wh.x * wh.x + self.ey * wh.y * wh.y) / ds)) / \
                    (4. * wo.dot(wh)), wi]
        else:
            return [0., wi]