Comment by 20k
5 days ago
>poorly designed third party APIs
I think this is missing the reason why these APIs are designed like this: because they're convenient and intuitive
Its rare that this kind of performance matters, or that the minor imprecisions of this kind of code matter at all. While its certainly true that we can write a better composite function, it also means that.. we have to write a completely new function for it
Breaking things up into simple, easy to understand, reusable representations is good. The complex part about this kinds of maths is not the code, its breaking up what you're trying to do into a set of abstracted concepts so that it doesn't turn into a maintenance nightmare
Where this really shows up more obviously is in more real-world library: axis angle rotations are probably a strong type with a lot of useful functions attached to it, to make your life easier. For maths there is always an abstraction penalty, but its usually worth the time saved, because 99.9999% of the time it simply doesn't matter
Add on top of this that this code would be optimised away with -ffast-math, and its not really relevant most of the time. I think everyone goes through this period when they think "lots of this trig is redundant, oh no!", but the software engineering takes priority generally
Based on my experience writing many games that work great barring the occasional random physics engine explosion, I suspect that trigonometry is responsible for a significant proportion of glitches.
I think over the years I subconsciously learned to avoid trig because of the issues mentioned, but I do still fall back to angles, especially for things like camera rotation. I am curious how far the OP goes with this crusade in their production code.
Yes, for physics engines I think that's a very good use case when its worth the extra complexity for robustness. Generally I think if errors (or especially nan's) can meaningfully compound, ie if you have persistent state, that's when its a good idea to do a deeper investigation
Your response is well-grounded--trig is trouble. Angles are often fine, but many 3rd party library functions are not.
Have you ended up with a set of self-implemented tools that you reuse?
You can definitely handle camera rotation via vector operations on rotation matrices.
My experience is that it's really easy to subtly fuck something up if you're doing a bunch of trig in code. If there's something subtly wrong somewhere, everything seems to work for a while, then one day you hit gimbal lock. Then you have to add a special case. Then you hit gimbal lock somewhere else in the code. Or you have tan spit out +/- infinity or NaN. Another special case. Or you have acos or asin in their degenerate regions where the minor imprecision isn't minor anymore, it's catastrophic imprecision. Another special case. Trig heavy code will work 0% of the time if you have an obvious bug, or will work 99% of the time if you a subtle bug, and once you start chasing that long tail you're just adding 9s and will never get to 100%. And if you have code that will run thousands/millions of times per frame, you need a lot of 9s to make sure a user can get through minutes or hours of using your software without hitting bugs.
Doing the same work sticking strictly to vectors and matrices tends to either not work at all or be bulletproof.
The other thing is that trig tends to build complexity very quickly. It's fine if you're doing a single rotation and a single translation, but once you start composing nested transformations it all goes to shit.
Or maybe you're substantially better at trig than I am. I've only been doing trig for 30 years, so I still have a lot to learn before I stop making the same sophomore mistakes.
> I think this is missing the reason why these APIs are designed like this: because they're convenient and intuitive
Agreed. In my view, the method the author figured out is far from intuitive for the general population, including me.
I guess the point is: How often do we really need actual angles in the code? Probably only at the very ends: input from users and output to users. Everywhere else, we should just be treating them as sin/cos pairs or dot/cross pairs. So when the user inputs an angle, immediately convert it to what the computer actually needs, store it that way throughout the computation, and then only if/when the user needs to see an actual angle would you need to convert it back.
This is how most physics/graphics engines work.