From 276cf1c2e02a4b6f56b88303c01c5bfb2e93c45e Mon Sep 17 00:00:00 2001 From: Steve Hollasch Date: Thu, 22 Aug 2024 12:11:24 -0700 Subject: [PATCH] Small improvement to rotate_y::hit() function Resolves #1484 --- CHANGELOG.md | 1 + books/RayTracingTheNextWeek.html | 43 +++++++++++++++++++------------- src/TheNextWeek/hittable.h | 43 +++++++++++++++++++------------- src/TheRestOfYourLife/hittable.h | 43 +++++++++++++++++++------------- 4 files changed, 76 insertions(+), 54 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a196a9c..107c6927 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ Change Log / Ray Tracing in One Weekend - Fix -- Big improvement to print version listing font size (#1595) and more compact line height for code listings in both print and browser. - Change -- Include hittable.h from material.h; drop `hit_record` forward declaration (#1609) + - Fix -- Slight improvement to `rotate_y::hit()` function (#1484) ### In One Weekend - Fix -- Fixed usage of the term "unit cube" for a cube of diameter two (#1555, #1603) diff --git a/books/RayTracingTheNextWeek.html b/books/RayTracingTheNextWeek.html index f06ddb09..8d154b9f 100644 --- a/books/RayTracingTheNextWeek.html +++ b/books/RayTracingTheNextWeek.html @@ -3815,34 +3815,41 @@ public: bool hit(const ray& r, interval ray_t, hit_record& rec) const override { - // Change the ray from world space to object space - auto origin = r.origin(); - auto direction = r.direction(); - origin[0] = cos_theta*r.origin()[0] - sin_theta*r.origin()[2]; - origin[2] = sin_theta*r.origin()[0] + cos_theta*r.origin()[2]; + // Transform the ray from world space to object space. - direction[0] = cos_theta*r.direction()[0] - sin_theta*r.direction()[2]; - direction[2] = sin_theta*r.direction()[0] + cos_theta*r.direction()[2]; + auto origin = point3( + (cos_theta * r.origin().x()) - (sin_theta * r.origin().z()), + r.origin().y(), + (sin_theta * r.origin().x()) + (cos_theta * r.origin().z()) + ); + + auto direction = vec3( + (cos_theta * r.direction().x()) - (sin_theta * r.direction().z()), + r.direction().y(), + (sin_theta * r.direction().x()) + (cos_theta * r.direction().z()) + ); ray rotated_r(origin, direction, r.time()); - // Determine whether an intersection exists in object space (and if so, where) + // Determine whether an intersection exists in object space (and if so, where). + if (!object->hit(rotated_r, ray_t, rec)) return false; - // Change the intersection point from object space to world space - auto p = rec.p; - p[0] = cos_theta*rec.p[0] + sin_theta*rec.p[2]; - p[2] = -sin_theta*rec.p[0] + cos_theta*rec.p[2]; + // Transform the intersection from object space back to world space. - // Change the normal from object space to world space - auto normal = rec.normal; - normal[0] = cos_theta*rec.normal[0] + sin_theta*rec.normal[2]; - normal[2] = -sin_theta*rec.normal[0] + cos_theta*rec.normal[2]; + rec.p = point3( + (cos_theta * rec.p.x()) + (sin_theta * rec.p.z()), + rec.p.y(), + (-sin_theta * rec.p.x()) + (cos_theta * rec.p.z()) + ); - rec.p = p; - rec.normal = normal; + rec.normal = vec3( + (cos_theta * rec.normal.x()) + (sin_theta * rec.normal.z()), + rec.normal.y(), + (-sin_theta * rec.normal.x()) + (cos_theta * rec.normal.z()) + ); return true; } diff --git a/src/TheNextWeek/hittable.h b/src/TheNextWeek/hittable.h index 9379b31a..4e405e3e 100644 --- a/src/TheNextWeek/hittable.h +++ b/src/TheNextWeek/hittable.h @@ -115,34 +115,41 @@ class rotate_y : public hittable { } bool hit(const ray& r, interval ray_t, hit_record& rec) const override { - // Change the ray from world space to object space - auto origin = r.origin(); - auto direction = r.direction(); - origin[0] = cos_theta*r.origin()[0] - sin_theta*r.origin()[2]; - origin[2] = sin_theta*r.origin()[0] + cos_theta*r.origin()[2]; + // Transform the ray from world space to object space. - direction[0] = cos_theta*r.direction()[0] - sin_theta*r.direction()[2]; - direction[2] = sin_theta*r.direction()[0] + cos_theta*r.direction()[2]; + auto origin = point3( + (cos_theta * r.origin().x()) - (sin_theta * r.origin().z()), + r.origin().y(), + (sin_theta * r.origin().x()) + (cos_theta * r.origin().z()) + ); + + auto direction = vec3( + (cos_theta * r.direction().x()) - (sin_theta * r.direction().z()), + r.direction().y(), + (sin_theta * r.direction().x()) + (cos_theta * r.direction().z()) + ); ray rotated_r(origin, direction, r.time()); - // Determine whether an intersection exists in object space (and if so, where) + // Determine whether an intersection exists in object space (and if so, where). + if (!object->hit(rotated_r, ray_t, rec)) return false; - // Change the intersection point from object space to world space - auto p = rec.p; - p[0] = cos_theta*rec.p[0] + sin_theta*rec.p[2]; - p[2] = -sin_theta*rec.p[0] + cos_theta*rec.p[2]; + // Transform the intersection from object space back to world space. - // Change the normal from object space to world space - auto normal = rec.normal; - normal[0] = cos_theta*rec.normal[0] + sin_theta*rec.normal[2]; - normal[2] = -sin_theta*rec.normal[0] + cos_theta*rec.normal[2]; + rec.p = point3( + (cos_theta * rec.p.x()) + (sin_theta * rec.p.z()), + rec.p.y(), + (-sin_theta * rec.p.x()) + (cos_theta * rec.p.z()) + ); - rec.p = p; - rec.normal = normal; + rec.normal = vec3( + (cos_theta * rec.normal.x()) + (sin_theta * rec.normal.z()), + rec.normal.y(), + (-sin_theta * rec.normal.x()) + (cos_theta * rec.normal.z()) + ); return true; } diff --git a/src/TheRestOfYourLife/hittable.h b/src/TheRestOfYourLife/hittable.h index 5f6be725..fe4901aa 100644 --- a/src/TheRestOfYourLife/hittable.h +++ b/src/TheRestOfYourLife/hittable.h @@ -123,34 +123,41 @@ class rotate_y : public hittable { } bool hit(const ray& r, interval ray_t, hit_record& rec) const override { - // Change the ray from world space to object space - auto origin = r.origin(); - auto direction = r.direction(); - origin[0] = cos_theta*r.origin()[0] - sin_theta*r.origin()[2]; - origin[2] = sin_theta*r.origin()[0] + cos_theta*r.origin()[2]; + // Transform the ray from world space to object space. - direction[0] = cos_theta*r.direction()[0] - sin_theta*r.direction()[2]; - direction[2] = sin_theta*r.direction()[0] + cos_theta*r.direction()[2]; + auto origin = point3( + (cos_theta * r.origin().x()) - (sin_theta * r.origin().z()), + r.origin().y(), + (sin_theta * r.origin().x()) + (cos_theta * r.origin().z()) + ); + + auto direction = vec3( + (cos_theta * r.direction().x()) - (sin_theta * r.direction().z()), + r.direction().y(), + (sin_theta * r.direction().x()) + (cos_theta * r.direction().z()) + ); ray rotated_r(origin, direction, r.time()); - // Determine whether an intersection exists in object space (and if so, where) + // Determine whether an intersection exists in object space (and if so, where). + if (!object->hit(rotated_r, ray_t, rec)) return false; - // Change the intersection point from object space to world space - auto p = rec.p; - p[0] = cos_theta*rec.p[0] + sin_theta*rec.p[2]; - p[2] = -sin_theta*rec.p[0] + cos_theta*rec.p[2]; + // Transform the intersection from object space back to world space. - // Change the normal from object space to world space - auto normal = rec.normal; - normal[0] = cos_theta*rec.normal[0] + sin_theta*rec.normal[2]; - normal[2] = -sin_theta*rec.normal[0] + cos_theta*rec.normal[2]; + rec.p = point3( + (cos_theta * rec.p.x()) + (sin_theta * rec.p.z()), + rec.p.y(), + (-sin_theta * rec.p.x()) + (cos_theta * rec.p.z()) + ); - rec.p = p; - rec.normal = normal; + rec.normal = vec3( + (cos_theta * rec.normal.x()) + (sin_theta * rec.normal.z()), + rec.normal.y(), + (-sin_theta * rec.normal.x()) + (cos_theta * rec.normal.z()) + ); return true; }