Gnollrunner said:
However, I've found that some people are resistant to using double, but I don't really think the speed is an issue with a reasonably modern computer.
I considered using doubles for my planet renderer: see blog post, but ultimately decided against it in favor of a hierarchical coordinate system. The main factor in my decisions were:
- Doubles don't even get you that far in practice. They're still not sufficient for anything farther than around the orbit of Pluto, depending on your precision requirements. This was not enough for me, because I want to have larger star systems and galaxies.
- My physics engine is highly optimized using 4-way float32 SIMD for almost all calculations. This could potentially be rewritten in AVX double precision (at large effort), but not all operations translate well (e.g. cross-lane shuffles), and there are problems on the edge cases. E.g. what happens when doing mesh collision when your mesh data is float32 but your transform matrices are float64? this causes lots of unnecessary conversions that slow things down. The instructions are roughly the same speed according to Intel, so it's more about memory bandwidth/cache I think (a double 4x4 matrix uses 2 cache lines instead of 1).
- Problems interfacing with GPU, which only takes float32 in most cases.
In contrast, a hierarchical coordinate system is more complex for some operations, but it wasn't that bad in practice to implement. It only took about 2 weeks to completely overhaul my engine to use it (including graphics, physics, and acoustic simulation, all custom implementations).
The general structure is that every object in the scene has a pointer to a CoordinateFrame object, which represents the local origin that an object is attached to. Each frame has a double-precision offset from the parent frame, and a local rotation matrix (float32). Within the same frame (about 3.2 km in size), all math is fast and easy. Only for far away objects do you pay any price for the extra math required to handle the transformations between frames, and even then the cost is not that high with SIMD optimizations. I have a few functions that make this easy: given two points in two different frames, produce the unit vector in each frame that points at the other point, as well as a distance between (double precision). This function walks the hierarchy between two frames to determine the relative vector with the best possible precision. This function can be used to implement most of what you need in a game engine for rendering and physics.