コード例 #1
0
    def hit(self, r: RayList, t_min: float, t_max: Union[float, cp.ndarray]) \
            -> HitRecordList:
        if isinstance(t_max, (int, float, cp.floating)):
            t_max_list = cp.full(len(r), t_max, cp.float32)
        else:
            t_max_list = t_max

        oc: Vec3List = r.origin() - self.center
        a: cp.ndarray = r.direction().length_squared()
        half_b: cp.ndarray = oc @ r.direction()
        c: cp.ndarray = oc.length_squared() - self.radius**2
        discriminant_list: cp.ndarray = half_b**2 - a*c

        discriminant_condition = discriminant_list > 0
        if not discriminant_condition.any():
            return HitRecordList.new(len(r)).set_compress_info(None)

        # Calculate t
        positive_discriminant_list = (
            discriminant_list * discriminant_condition
        )
        root = cp.sqrt(positive_discriminant_list)
        non_zero_a = a - (a == 0)
        t_0 = (-half_b - root) / non_zero_a
        t_1 = (-half_b + root) / non_zero_a

        # Choose t
        t_0_condition = (
            (t_min < t_0) & (t_0 < t_max_list) & discriminant_condition
        )
        t_1_condition = (
            (t_min < t_1) & (t_1 < t_max_list)
            & (~t_0_condition) & discriminant_condition
        )
        t = cp.where(t_0_condition, t_0, 0)
        t = cp.where(t_1_condition, t_1, t)

        # Compression
        condition = t > 0
        full_rate = condition.sum() / len(t)
        if full_rate > 0.5:
            idx = None
        else:
            idx = cp.where(condition)[0]
            t = t[idx]
            r = RayList(
                Vec3List(r.orig.get_ndarray(idx)),
                Vec3List(r.dir.get_ndarray(idx))
            )

        # Wrap up result
        point = r.at(t)
        outward_normal = (point - self.center) / self.radius

        result = HitRecordList(
            point, t, cp.full(len(r), self.material.idx, dtype=cp.int32)
        ).set_face_normal(r, outward_normal).set_compress_info(idx)

        return result
コード例 #2
0
ファイル: sphere.py プロジェクト: SteveHawk/RayTracing-Py
    def hit(self, r: RayList, t_min: float, t_max: Union[float, np.ndarray]) \
            -> HitRecordList:
        if isinstance(t_max, (int, float, np.floating)):
            t_max_list = np.full(len(r), t_max)
        else:
            t_max_list = t_max

        oc: Vec3List = r.origin() - self.center
        a: np.ndarray = r.direction().length_squared()
        half_b: np.ndarray = oc @ r.direction()
        c: np.ndarray = oc.length_squared() - self.radius**2
        discriminant_list: np.ndarray = half_b**2 - a * c

        discriminant_condition = discriminant_list > 0
        if not discriminant_condition.any():
            return HitRecordList.new(len(r))

        positive_discriminant_list = (discriminant_list *
                                      discriminant_condition)
        root = np.sqrt(positive_discriminant_list)
        non_zero_a = a - (a == 0)
        t_0 = (-half_b - root) / non_zero_a
        t_1 = (-half_b + root) / non_zero_a

        t_0_condition = ((t_min < t_0) & (t_0 < t_max_list)
                         & discriminant_condition)
        t_1_condition = ((t_min < t_1) & (t_1 < t_max_list)
                         & (~t_0_condition) & discriminant_condition)
        t = np.where(t_0_condition, t_0, 0)
        t = np.where(t_1_condition, t_1, t)

        point = r.at(t)
        outward_normal = (point - self.center) / self.radius

        result = HitRecordList(point, t, np.full(
            len(r), self.material.idx)).set_face_normal(r, outward_normal)

        return result