I found the fucker. The rays were bouncing incorrectly because I wasn't
holding a value the way I should have. I thought I was being clever and
using Rusts's ability to redeclare variables. But, no. That value is
meant to be modified when the first conditional passes. The outcomes are
3 possibilities, where one is an early return. Shadowing the value that
way meant I was giving back garbage.
I don't know why this didn't have any obviously bad effects prior to
making the dielectric material.
The Vec3::as_unit() function accepts input by reference. It passes back
out a copy, however, and some inputs are even temporaries. I bet the
optimizer can see through this game and will do the right thing if I
give it a value instead. It should perform copy elision as appropriate,
even if I'm missing out on Rust's move semantics here.
Remove some old, unused, and unuseable functions.
Dielectric material matching Raytracing in a Weekend book chapter 10.2.
But it isn't right. The spheres turn into solid black holes.
As I'm making the commit, I've found the problem. I'm separating it out
so I can tag it and explore the code a bit more. See the step-by-step
changes, and such.
Segfaults and stack overflows. I get overflows when running in either
debug or release. Segmentation faults when hooked up to GDB. I think it
may be related to the copying of uninitialized trait objects, but I
don't know.
I've decided the trait-based interface just isn't worth this. I'll
rearrange the materials into an Enum and a big match block.
I get lazy with commits when following guided material. There's a design
challenge to approach, now. I'm saving here so I can revert changes in
case it goes sideways.
Materials are proving to be a little complicated in Rust semantics. The
Ray Tracing in a Weekend book uses shared_ptr's, but Rust doesn't really
like that. I'm doing references with lifetime annotations. Hopefully I
can get that the right way around to work out.
The materials themselves look like reasonable candidates for describing
as Enums. This takes away the ability to add new ones by simply impl'ing
a trait, but that was never gonna happen anyway. The code would be
modified and recompiled. There's no difference in maintenance cost if
that's a new struct impl'ing a trait, or adding enum members.