Day 23, Cubes
All core functionality is in place, so time for more shapes. First up is cubes, the volume contained by three perpendicular pairs of parallel planes, and aligned with the axes. So planar ray intersection with each one, and pick the snuggest fit to intersect the cube. Not quite pixel ready yet, so something for tomorrow.
The tricky bit is that when any component of the ray direction is zero, intersections with some of the planes causes the intersection equation \(o + \overrightarrow{d}t = 0\) to divide by zero, and for near misses even zero divide by zero. Since \(0/0 \rightarrow NaN\) that is detected and replaced by \(+Inf\). The other divisions by zero gives the correct \(±Inf\) for Ruby Float
s, so that’s fine out of the box.
def nonan_div(numerator, denominator)
return numerator / denominator unless numerator.zero? && denominator.zero?
Float::INFINITY
end
Next related
Day 24 – 25, Cubemas
Oh my god, it’s full of cubes! The scene consists of 8 cubes, two for the room, five for the table, and the traditional cubemas decoration of one glass cube on the table.
Previous related
Day 22, Murky waters
Remember when we introduced shadows? Casting a ray towards the light and see if any object is in the way. Well, that’s a huge shortcut, because transparent materials. Well, why not fix that by taking another huge shortcut, and add a toggle to exclude certain objects from shadow ray casting?
Day 18 – 21, Feverish Shiny Glass Pixels
Day 17, Transparency and Refraction
No new pixels today, because implementing transparency and refraction turned out to be quite a lot of work. So far I’ve made all the cases where nothing happens, and the refracted ray would be black.