예제 #1
0
    def build_from_w(self, n: Vector3):
        self._w = Vector3.normalize(n)
        if math.fabs(self._w.x()) > 0.9:
            a = Vector3(0, 1, 0)
        else:
            a = Vector3(1, 0, 0)

        self._v = Vector3.normalize(Vector3.cross(self._w, a))
        self._u = Vector3.cross(self._w, self._v)
예제 #2
0
    def calculate_ray_color(self, ray: Ray, depth: float):
        has_hit, hit_record = self._bvh_world.hit(ray=ray,
                                                  t_min=0.001,
                                                  t_max=float('inf'))

        if has_hit is True:
            scattered, attenuation = hit_record.material.scatter(
                ray_incident=ray, hit_record=hit_record)

            emitted = hit_record.material.emitted(u=hit_record.u,
                                                  v=hit_record.v,
                                                  p=hit_record.hit_point)
            if depth < 50 and scattered is not None:
                return emitted + attenuation * self.calculate_ray_color(
                    ray=scattered, depth=depth + 1)
            else:
                return emitted

        else:
            # Ambient Color
            # return Vector3(0.0, 0.0, 0.0)
            ray_direction = Vector3.normalize(ray.direction)
            t = 0.5 * (ray_direction.y() + 1.0)
            return (1.0 - t) * Vector3(0.2, 0.2, 0.2) + t * Vector3(
                0.5, 0.7, 1.0)
예제 #3
0
 def perlin_generate(self):
     p = list()
     for i in range(256):
         p.append(
             Vector3.normalize(
                 Vector3(-1 + 2 * random.random(), -1 + 2 * random.random(),
                         -1 + 2 * random.random())))
     return p
예제 #4
0
    def __init__(self, lookfrom:'Vector3', lookat:'Vector3', vectorup:'Vector3', vfov:'float', aspect:'float', aperture:'float', focus_dist:'float', t0:float, t1:float):
        theta =  vfov * math.pi / 180  # vfov to radians
        half_height = math.tan(theta / 2) # h = tan(theta / 2)
        half_width = half_height * aspect

        self._lens_radius = aperture / 2

        self._time0 = t0
        self._time1 = t1

        self._camera_origin = lookfrom
        w = Vector3.normalize(lookfrom - lookat)
        u = Vector3.normalize(Vector3.cross(vectorup, w))
        v = Vector3.cross(w, u)

        self._lower_left_corner = self._camera_origin - half_width * focus_dist * u - half_height * focus_dist * v - focus_dist*w
        self._horizontal = 2 * half_width * focus_dist * u
        self._vertical = 2 * half_height * focus_dist * v
예제 #5
0
    def get_sphere_uv(self, p: Vector3) -> (float, float):
        """Get the uv coordinates of a point in the sphere"""
        d = Vector3.normalize(p - self._center)

        phi = math.atan2(d.z(), d.x()) / (2 * math.pi)
        u = phi + 0.5

        v = 0.5 - (math.asin(d.y()) / math.pi)
        return u, v
예제 #6
0
    def scatter(self, ray_incident: Ray, hit_record: HitRecord):

        reflected_vector = Vector3.reflect(
            Vector3.normalize(ray_incident.direction),
            hit_record.hit_point_normal)
        attenuation = Vector3(1.0, 1.0, 1.0)

        refracted_vector = Vector3.refract(incident=ray_incident.direction,
                                           normal=hit_record.hit_point_normal,
                                           n1=1.0,
                                           n2=self._refraction_index)
        reflect_probability = self.schlick(incident=ray_incident.direction,
                                           normal=hit_record.hit_point_normal,
                                           n1=1.0,
                                           n2=self._refraction_index)

        if random.random() < reflect_probability:
            scattered = Ray(hit_record.hit_point, reflected_vector,
                            ray_incident.time)
        else:
            scattered = Ray(hit_record.hit_point, refracted_vector,
                            ray_incident.time)

        return scattered, attenuation
예제 #7
0
 def value(self, direction: Vector3) -> float:
     cosine = Vector3.dot(Vector3.normalize(direction), self._uvw.w())
     if cosine > 0:
         return cosine / math.pi
     else:
         return 0