summaryrefslogtreecommitdiff
path: root/sphere.h
diff options
context:
space:
mode:
authorKeuin <[email protected]>2022-04-12 23:04:25 +0800
committerKeuin <[email protected]>2022-04-12 23:04:25 +0800
commit8c3cbfaeec0f3055aba9bfe4b2bdfab7ff93bf1b (patch)
tree58c032fc5dd4118d42238b03c25663d281513a67 /sphere.h
parentc30f3650287c95742b3674299f4c3e3549db6f5e (diff)
Refactor: move hitlist, object, sphere, viewport into single files.
Add bias_ctx for setting sub-pixel sampling bias.
Diffstat (limited to 'sphere.h')
-rw-r--r--sphere.h81
1 files changed, 81 insertions, 0 deletions
diff --git a/sphere.h b/sphere.h
new file mode 100644
index 0000000..f604b74
--- /dev/null
+++ b/sphere.h
@@ -0,0 +1,81 @@
+//
+// Created by Keuin on 2022/4/12.
+//
+
+#ifndef RT_SPHERE_H
+#define RT_SPHERE_H
+
+#include "object.h"
+#include "hitlist.h"
+#include "viewport.h"
+#include "timer.h"
+#include "bitmap.h"
+#include "ray.h"
+#include "vec.h"
+#include <cstdlib>
+#include <memory>
+#include <limits>
+#include <vector>
+#include <iostream>
+#include <cstdint>
+
+class sphere : public object {
+ vec3d center;
+ double radius;
+
+public:
+ sphere() = delete;
+
+ sphere(const vec3d &center, double radius) : center(center), radius(radius) {}
+
+ ~sphere() override = default;
+
+ vec3d normal_vector(const vec3d &where) const override {
+ // We assume the point is on surface, speeding up the normalization
+ return (where - center) / radius;
+ }
+
+ bool hit(const ray3d &r, double &t, double t1, double t2) const override {
+ // Ray: {Source, Direction, time}
+ // Sphere: {Center, radius}
+ // sphere hit formula: |Source + Direction * time - Center| = radius
+ // |(Sx + Dx * t - Cx, Sy + Dy * t - Cy, Sz + Dz * t - Cz)| = radius
+
+ const auto c2s = r.source() - center; // center to source
+ // A = D dot D
+ const double a = r.direction().mod2();
+ // H = (S - C) dot D
+ const auto h = dot(c2s, r.direction());
+ // B = 2H ( not used in our optimized routine )
+ // C = (S - C) dot (S - C) - radius^2
+ const double c = c2s.mod2() - radius * radius;
+ // 4delta = H^2 - AC
+ // delta_q = H^2 - AC (quarter delta)
+ const double delta_q = h * h - a * c;
+
+ bool hit = false;
+ if (delta_q >= 0) {
+ // return the root in range [t1, t2]
+ // t = ( -H +- sqrt{ delta_q } ) / A
+ double root;
+ root = (-h - sqrt(delta_q)) / a;
+ if (root >= t1 && root <= t2) {
+ hit = true;
+ t = root;
+ } else {
+ root = (-h + sqrt(delta_q)) / a;
+ if (root >= t1 && root <= t2) {
+ hit = true;
+ t = root;
+ }
+ }
+ }
+ return hit;
+ }
+
+ pixel8b color() const override {
+ return pixel8b::from_normalized(1.0, 0.0, 0.0);
+ }
+};
+
+#endif //RT_SPHERE_H