From a2e0c07c6a63539776b108f8ac88cd4781449aab Mon Sep 17 00:00:00 2001 From: Cyberarm Date: Wed, 7 Aug 2019 23:03:40 -0500 Subject: [PATCH] Added Ray class --- lib/cyberarm_engine.rb | 1 + lib/cyberarm_engine/lib/ray.rb | 55 ++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 lib/cyberarm_engine/lib/ray.rb diff --git a/lib/cyberarm_engine.rb b/lib/cyberarm_engine.rb index 89ba8c2..70cad80 100644 --- a/lib/cyberarm_engine.rb +++ b/lib/cyberarm_engine.rb @@ -9,6 +9,7 @@ require_relative "cyberarm_engine/engine" require_relative "cyberarm_engine/lib/bounding_box" require_relative "cyberarm_engine/lib/vector" +require_relative "cyberarm_engine/lib/ray" require_relative "cyberarm_engine/lib/shader" if defined?(OpenGL) require_relative "cyberarm_engine/background" diff --git a/lib/cyberarm_engine/lib/ray.rb b/lib/cyberarm_engine/lib/ray.rb new file mode 100644 index 0000000..6806c4b --- /dev/null +++ b/lib/cyberarm_engine/lib/ray.rb @@ -0,0 +1,55 @@ +module CyberarmEngine + class Ray + def initialize(origin, direction) + raise "Origin must be a Vector!" unless origin.is_a?(Vector) + raise "Direction must be a Vector!" unless direction.is_a?(Vector) + + @origin = origin + @direction = direction + + @inverse_direction = @direction.inverse + end + + def intersect?(intersectable) + if intersectable.is_a?(BoundingBox) + intersect_bounding_box?(intersectable) + else + raise NotImplementedError, "Ray intersection test for #{intersectable.class} not implemented." + end + end + + # Based on: https://tavianator.com/fast-branchless-raybounding-box-intersections/ + def intersect_bounding_box?(box) + tmin = -Float::INFINITY + tmax = Float::INFINITY + + tx1 = (box.min.x - @origin.x) * @inverse_direction.x + tx2 = (box.max.x - @origin.x) * @inverse_direction.x + + tmin = max(tmin, min(tx1, tx2)) + tmax = min(tmax, max(tx1, tx2)) + + ty1 = (box.min.y - @origin.y) * @inverse_direction.y + ty2 = (box.max.y - @origin.y) * @inverse_direction.y + + tmin = max(tmin, min(ty1, ty2)) + tmax = min(tmax, max(ty1, ty2)) + + tz1 = (box.min.z - @origin.z) * @inverse_direction.z + tz2 = (box.max.z - @origin.z) * @inverse_direction.z + + tmin = max(tmin, min(tz1, tz2)) + tmax = min(tmax, max(tz1, tz2)) + + return tmax >= max(tmin, 0.0); + end + + def min(x, y) + ((x) < (y) ? (x) : (y)) + end + + def max(x, y) + ((x) > (y) ? (x) : (y)) + end + end +end \ No newline at end of file