| #ifndef SPHERE_H |
| #define SPHERE_H |
| //============================================================================================== |
| // Originally written in 2016 by Peter Shirley <ptrshrl@gmail.com> |
| // |
| // To the extent possible under law, the author(s) have dedicated all copyright |
| // and related and neighboring rights to this software to the public domain |
| // worldwide. This software is distributed without any warranty. |
| // |
| // You should have received a copy (see file COPYING.txt) of the CC0 Public |
| // Domain Dedication along with this software. If not, see |
| // <http://creativecommons.org/publicdomain/zero/1.0/>. |
| // |
| // The original source code is from |
| // https://github.com/RayTracing/raytracing.github.io/tree/release/src/TheNextWeek |
| // |
| // Changes to the original code follow the following license. |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| //============================================================================================== |
| |
| #include "rtweekend.h" |
| |
| #include "hittable.h" |
| |
| |
| class sphere : public hittable { |
| public: |
| // Stationary Sphere |
| __host__ __device__ sphere(point3 _center, double _radius, |
| SharedPtr<material> _material) |
| : center1(_center), radius(_radius), mat(_material), is_moving(false) |
| { |
| auto rvec = vec3(radius, radius, radius); |
| bbox = aabb(center1 - rvec, center1 + rvec); |
| } |
| |
| // Moving Sphere |
| __host__ __device__ sphere(point3 _center1, point3 _center2, double _radius, SharedPtr<material> _material) |
| : center1(_center1), radius(_radius), mat(_material), is_moving(true) |
| { |
| auto rvec = vec3(radius, radius, radius); |
| aabb box1(_center1 - rvec, _center1 + rvec); |
| aabb box2(_center2 - rvec, _center2 + rvec); |
| bbox = aabb(box1, box2); |
| |
| center_vec = _center2 - _center1; |
| } |
| |
| __host__ __device__ bool hit(const ray &r, interval ray_t, hit_record &rec, |
| unsigned &rng) const override { |
| point3 center = is_moving ? sphere_center(r.time()) : center1; |
| vec3 oc = r.origin() - center; |
| auto a = r.direction().length_squared(); |
| auto half_b = dot(oc, r.direction()); |
| auto c = oc.length_squared() - radius * radius; |
| |
| auto discriminant = half_b * half_b - a * c; |
| if (discriminant < 0) |
| return false; |
| |
| // Find the nearest root that lies in the acceptable range. |
| auto sqrtd = sqrt(discriminant); |
| auto root = (-half_b - sqrtd) / a; |
| if (!ray_t.surrounds(root)) { |
| root = (-half_b + sqrtd) / a; |
| if (!ray_t.surrounds(root)) |
| return false; |
| } |
| |
| rec.t = root; |
| rec.p = r.at(rec.t); |
| vec3 outward_normal = (rec.p - center) / radius; |
| rec.set_face_normal(r, outward_normal); |
| get_sphere_uv(outward_normal, rec.u, rec.v); |
| rec.mat = mat; |
| |
| return true; |
| } |
| |
| __host__ __device__ aabb bounding_box() const override { return bbox; } |
| |
| private: |
| point3 center1; |
| double radius; |
| SharedPtr<material> mat; |
| bool is_moving; |
| vec3 center_vec; |
| aabb bbox; |
| |
| __host__ __device__ point3 sphere_center(double time) const { |
| // Linearly interpolate from center1 to center2 according to time, where t=0 yields |
| // center1, and t=1 yields center2. |
| return center1 + time*center_vec; |
| } |
| |
| __host__ __device__ static void get_sphere_uv(const point3& p, double& u, double& v) { |
| // p: a given point on the sphere of radius one, centered at the origin. |
| // u: returned value [0,1] of angle around the Y axis from X=-1. |
| // v: returned value [0,1] of angle from Y=-1 to Y=+1. |
| // <1 0 0> yields <0.50 0.50> <-1 0 0> yields <0.00 0.50> |
| // <0 1 0> yields <0.50 1.00> < 0 -1 0> yields <0.50 0.00> |
| // <0 0 1> yields <0.25 0.50> < 0 0 -1> yields <0.75 0.50> |
| |
| auto theta = acos(-p.y()); |
| auto phi = atan2(-p.z(), p.x()) + pi; |
| |
| u = phi / (2*pi); |
| v = theta / pi; |
| } |
| }; |
| |
| |
| #endif |