summaryrefslogtreecommitdiff
path: root/main_simple_scanner.cpp
diff options
context:
space:
mode:
authorKeuin <[email protected]>2022-04-12 11:01:32 +0800
committerKeuin <[email protected]>2022-04-12 11:01:32 +0800
commita97b38299d5f8297d15077160df5439d274bd571 (patch)
treeb2f86794894561a853a6873a37ea14e4f7e7387c /main_simple_scanner.cpp
parente83da6c36b39e6f8de35fc7e1c3caf8041cfe325 (diff)
Make object::hit provides hit time t.
Visualize normal vector at hit point. Add pixel<T>::from_normalized(const vec3d&) for visualizing normal vector.
Diffstat (limited to 'main_simple_scanner.cpp')
-rw-r--r--main_simple_scanner.cpp31
1 files changed, 25 insertions, 6 deletions
diff --git a/main_simple_scanner.cpp b/main_simple_scanner.cpp
index 7279e12..e57ef03 100644
--- a/main_simple_scanner.cpp
+++ b/main_simple_scanner.cpp
@@ -17,8 +17,11 @@
class object {
public:
- // Will the given ray hit.
- virtual bool hit(const ray3d &r) const = 0;
+ // Will the given ray hit. Returns time t if hits.
+ virtual bool hit(const ray3d &r, double &t) const = 0;
+
+ // Given a point on the surface, returns the normalized normal vector on that point.
+ virtual vec3d normal_vector(const vec3d &where) const = 0;
// object color, currently not parameterized
virtual pixel8b color() const = 0;
@@ -38,7 +41,12 @@ public:
~sphere() override = default;
- bool hit(const ray3d &r) const override {
+ 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) const override {
// Ray: {Source, Direction, time}
// Sphere: {Center, radius}
// sphere hit formula: |Source + Direction * time - Center| = radius
@@ -51,7 +59,13 @@ public:
const auto rel_src = r.source() - center; // relative position of ray source
// C = (S - C) dot (S - C) - radius^2
const double c = dot(rel_src, rel_src) - radius * radius;
- return b * b - 4 * a * c >= 0;
+ const auto delta = b * b - 4 * a * c;
+ const auto hit = delta >= 0;
+ if (hit) {
+ // the smaller root is the first point the ray hits, so return that one
+ t = (-b - sqrt(delta)) / (2.0 * a);
+ }
+ return hit;
}
pixel8b color() const override {
@@ -67,9 +81,14 @@ class viewport {
// Given a ray from the camera, generate a color the camera seen on the viewport.
pixel8b color(const ray3d &r) {
// Detect hits
+ double hit_t;
for (const auto &obj: objects) {
- if (obj->hit(r)) {
- return obj->color();
+ if (obj->hit(r, hit_t)) {
+ // normal vector on hit point
+ const auto nv = obj->normal_vector(r.at(hit_t));
+// return obj->color();
+ // visualize normal vector at hit point
+ return pixel8b::from_normalized(nv);
}
}