예제 #1
0
    def hit(self, ray: Ray, t_min: float, t_max: float,
            rec: HitRecord) -> bool:

        oc = ray.origin - self.cen

        a = ray.direction.dot(ray.direction)
        b = oc.dot(ray.direction)
        c = oc.dot(oc) - self.rsquared
        discriminant = b * b - a * c

        if discriminant > 0:
            d_sqrt = discriminant**0.5
            temp = (-b - d_sqrt) / (a)
            if temp < t_max and temp > t_min:
                rec.t = temp
                rec.p = ray.point_at_parameter(temp)
                rec.normal = (rec.p - self.cen) / self.r
                rec.material = self.material
                return True

            temp = (-b + d_sqrt) / (a)
            if temp < t_max and temp > t_min:
                rec.t = temp
                rec.p = ray.point_at_parameter(temp)
                rec.normal = (rec.p - self.cen) / self.r
                rec.material = self.material
                return True

        return False
예제 #2
0
    def hit(self, r: Ray, t_min: float, t_max: float):
        oc = r.origin() - self.center
        a = np.dot(r.direction(), r.direction())
        b = np.dot(oc, r.direction())
        c = np.dot(oc, oc) - self.radius * self.radius
        discriminant = b * b - a * c

        if discriminant > 0:
            temp = (-b - sqrt(b * b - a * c)) / a
            if (temp < t_max) and (temp > t_min):
                t = temp
                p = r.point_at_parameter(t)
                normal = (p - self.center) / self.radius
                rec = hit_record(t, p, normal, self.material)
                return True, rec

            temp = (-b + sqrt(b * b - a * c)) / a
            if (temp < t_max) and (temp > t_min):
                t = temp
                p = r.point_at_parameter(t)
                normal = (p - self.center) / self.radius
                rec = hit_record(t, p, normal, self.material)
                return True, rec

        return False, None
예제 #3
0
    def hit(self, ray: Ray, t_min: float, t_max: float, rec: hit_record):
        oc = ray.origin() - self.center
        a = Vector3.dot(ray.direction(), ray.direction())
        b = Vector3.dot(oc, ray.direction())
        c = Vector3.dot(oc, oc) - self.radius * self.radius
        discriminant = b * b - a * c

        if (discriminant > 0):
            temp = (-b - math.sqrt(discriminant)) / a
            if (temp < t_max and temp > t_min):
                rec.t = temp
                rec.p = ray.point_at_parameter(rec.t)
                rec.normal = (rec.p - self.center).scalar_div(self.radius)
                return True
            temp = (-b + math.sqrt(discriminant)) / a
            if (temp < t_max and temp > t_min):
                rec.t = temp
                rec.p = ray.point_at_parameter(rec.t)
                rec.normal = (rec.p - self.center).scalar_div(self.radius)
                return True

        return False
예제 #4
0
    def hit(self, r: Ray, t_min: float, t_max: float):
        t: float = (self.k - r.origin()[2]) / r.direction()[2]

        if (t < t_min) or (t > t_max):
            return False, None
        x: float = r.origin()[0] + t * r.direction()[0]
        y: float = r.origin()[1] + t * r.direction()[1]

        if (x < self.x0) or (x > self.x1) or (y < self.y0) or (y > self.y1):
            return False, None

        u = (x - self.x0) / (self.x1 - self.x0)
        v = (y - self.y0) / (self.y1 - self.y0)
        p = r.point_at_parameter(t)
        normal = np.array((0, 0, 1))

        return True, hit_record(t, p, normal, self.material, u, v)
예제 #5
0
    def test_sphere_hit(self):

        sphere = Sphere(np.array([0.2, -0.5, -1.4]), 0.8, None)

        # ray specified by origin and direction
        ray = Ray(np.array([0.3, 0.1, 0.4]), np.array([-0.1, -0.3, -1.]))

        # intersect ray with sphere
        rec, t = sphere.hit(ray, 0.1, 10.)

        self.assertAlmostEqual(
            np.linalg.norm(ray.point_at_parameter(t) - rec.point),
            0,
            delta=1e-14,
            msg='hit record must be consistent with ray parameter')

        self.assertAlmostEqual(
            abs(np.linalg.norm(rec.point - sphere.center) - sphere.radius),
            0,
            delta=1e-14,
            msg=
            'distance between hit point and sphere center must be equal to sphere radius'
        )
예제 #6
0
nx = 200
ny = 100

print('P3\n%d %d 255' % (nx, ny))

lower_left_corner = Vec3(-2.0, -1.0, -1.0)
horizontal = Vec3(4.0, 0.0, 0.0)
vertical = Vec3(0.0, 2.0, 0.0)
origin = Vec3(0.0, 0.0, 0.0)

hlist = [
    Sphere(Vec3(0.0, 0.0, -1.0), 0.5),
    Sphere(Vec3(0.0, -100.5, -1.0), 100.0)
]
world = HitableList(hlist)

for j in range(ny)[::-1]:
    for i in range(nx):
        u = float(i) / float(nx)
        v = float(j) / float(ny)
        r = Ray(origin, lower_left_corner + horizontal * u + vertical * v)

        p = r.point_at_parameter(2.0)
        col = color(r, world)
        ir = int(255.99 * col.r)
        ig = int(255.99 * col.g)
        ib = int(255.99 * col.b)

        print('%d %d %d' % (ir, ig, ib))
예제 #7
0
        unit_direction = r.direction.unit_vector()
        t = 0.5 * (unit_direction.y + 1.0)
        return Vec3(1.0, 1.0, 1.0) * (1.0 - t) + Vec3(0.5, 0.7, 1.0) * t

nx = 200
ny = 100

print('P3\n%d %d 255' % (nx, ny))

lower_left_corner = Vec3(-2.0, -1.0, -1.0)
horizontal = Vec3(4.0, 0.0, 0.0)
vertical = Vec3(0.0, 2.0, 0.0)
origin = Vec3(0.0, 0.0, 0.0)

hlist = [Sphere(Vec3(0.0, 0.0, -1.0), 0.5), Sphere(Vec3(0.0, -100.5, -1.0), 100.0)]
world = HitableList(hlist)

for j in range(ny)[::-1]:
    for i in range(nx):
        u = float(i) / float(nx)
        v = float(j) / float(ny)
        r = Ray(origin, lower_left_corner + horizontal * u + vertical * v)

        p = r.point_at_parameter(2.0)
        col = color(r, world)
        ir = int(255.99 * col.r)
        ig = int(255.99 * col.g)
        ib = int(255.99 * col.b)

        print('%d %d %d' % (ir, ig, ib))