It eschews angles entirely, sticking to ratios. It avoids square roots by sticking to "quadrances" (squared distance; i.e. pythagoras/euclidean-distance without taking square roots).
He's quite contrarian, so I'd take his informal statements with a pinch of salt (e.g. that there's no such thing as Real numbers; the underlying argument is reasonable, but the grand statements lose all that nuance); but he ends up approaching many subjects from an interesting perspective, and presents lots of nice connections e.g. between projective geometry, linear algebra, etc.
QuaternionsBhop 20 hours ago [-]
I also invented this! There is cool stuff like angle adding and angle doubling formulas, but the main downside is that you can only directly encode 180 degrees of rotation. I use it for FOV in my games internally! (With degrees as user input of course.) In order to actually use it to replace angles, I assume you'd want to use some sort of half angle system like quaternions. Even then you still have singularities, so it does have its warts.
srean 1 days ago [-]
He maybe considered contrarian but his math is sound.
zzless 1 days ago [-]
With all due respect, no, it isn't. His drivel against set theory shows that he didn't even read the basic axiomatic set theory texts. In one of his papers, he is ranting against the axiom of infinity saying that 'there exists an infinite set' is not a precise mathematical statement. However, the axiom of infinity does not say any such thing! It precisely states the existence of some object than can be thought of as infinite but does not assign any semantics to it. Ironically, if he looked deeper, he would realize that the most interesting set theoretic proofs (independence results) are really the results in basic arithmetic (although covered in a lot of abstractions) and thus no less 'constructive' than his rational trigonometry.
lich_king 1 days ago [-]
Almost every critique of the axiom of infinity is philosophical. I don't think you can just say "the axiom is sound, so what's your point". And you don't even get to claim that because of Godel's incompleteness theorem.
The axioms were not handed to us from above. They were a product of a thought process anchored to intuition about the real world. The outcomes of that process can be argued about. This includes the belief that the outcomes are wrong even if we can't point to any obvious paradox.
srean 1 days ago [-]
"Sound" means free of contradiction with respect to the axioms assumed.
If you can derive a contradiction using his methods of computation I would study that with interest.
By "sound" I do not mean provably sound. I mean I have not seen a proof of unsoundness yet.
fn-mote 1 days ago [-]
To clarify:
“Sound” != proof of soundness in the same way that the Riemann Hypothesis being true is not the same as RH being proven.
srean 1 days ago [-]
Not a bad analogy. Damn good.
kstrauser 1 days ago [-]
> "Sound" means free of contradiction with respect to the axioms assumed.
Gödel wept.
adrian_b 12 hours ago [-]
If with an axiomatic system there are undecidable propositions, that is not the same with the axiomatic system being contradictory, i.e. where you can prove that a proposition is both true and false.
An undecidable proposition is neither true nor false, it is not both true and false.
A system with undecidable propositions may be perfectly fine, while a contradictory system is useless.
Thus what the previous poster has said has nothing to do with what Gödel had proved.
Ensuring that the system of axioms that you use is non-contradictory has remained as useful today as by the time of Euclid and basing your reasoning on clearly stated non-contradictory axioms has also remained equally important, even if we are now aware that there may be undecidable things (which are normally irrelevant in practice anyway).
The results of Gödel may be interpreted as a demonstration that the use of ternary logic is unavoidable in mathematics, like it already was in real life, where it cannot always be determined whether a claim is true or false.
srean 10 hours ago [-]
Indeed. Soundness and completeness are different things.
There are two well accepted definitions of soundness. One of them is the inability to prove true == false, that is, one cannot prove a contradiction from within that axiomatic system.
lupire 3 hours ago [-]
They aren't completely different, because trying to achieve wine generally harms the other.
srean 44 minutes ago [-]
True, I guess you understood what I meant, that they are different things.
Indeed, as you allude, you cannot have both in an expressive enough system.
sublinear 1 days ago [-]
> It precisely states the existence of some object than can be thought of as infinite but does not assign any semantics to it
Can you elaborate on this? I think many understand that the "existence of some object" implies there is some semantic difference even if there isn't a practical one.
I really enjoyed Wildberger's take back in high school and college. It can be far more intuitive to avoid unnecessary invocation of calculation and abstraction when possible.
I think the main thrust of his argument was that if we're going to give in to notions of infinity, irrationals, etc. it should be when they're truly needed. Most students are being given the opposite (as early as possible and with bad examples) to suit the limited time given in school. He then asks if/where we really need them at all, and has yet to be answered convincingly enough (probably only because nobody cares).
keeganpoppen 1 days ago [-]
he sounds awesome. even though i’m sure i would view him as a total kook, he’s the kind of kook that life is brighter for everyone with his existence.
Razengan 1 days ago [-]
Stuff like this is what really interests me in trying to imagine how differently aliens might use things that we consider to be immutable fundamentals.
ajkjk 1 days ago [-]
personal theory: I think there's going to turn out to be a parallel development of math that is basically strictly finitist and never contends with the concept of an infinite set, much less the axiom of choice or any of its ilk. Which would require the foundation being something other than set theory. You basically do away with referring to the real numbers or the set of all natural numbers or anything like that, and skip all the parts of math that require them. I suspect that for any real-world purpose you basically don't lose anything. (This is a stance that I keep finding reinforced as a learn more math, but I don't really feel like I can defend it... it's a hunch I guess.)
lupire 3 hours ago [-]
That math exists, but it is annoying to work with.
donkeybeer 12 hours ago [-]
How would you do limits or analysis?
don-bright 13 hours ago [-]
I had this feeling of alien math when I went thru his videos on ancient Babylonian math. They were very serious about the everything divided by sixty stuff. Good times.
srean 1 days ago [-]
This has been some sort of a mix of peeve and a moment of enlightenment of mine when I understood this.
I wholeheartedly agree with the point being made in the post. I had commented about this in the recent asin() post but deleted thinking it might not be of general interest.
If you care about angles and rotations in the plane, it is often profitable to represent an angle not by a scalar such as a degree or a radian but as a tuple
(cos \theta, sin \theta)
or as a complex number.
This way one can often avoid calls to expensive trigonometric functions. One may need calls to square roots and general polynomial root finding.
In Python you can represent an angle as a unit complex numbers and the runtime will do the computations for you.
For example, if you needed the angular bisector of an angle subtended at the origin (you can translate the vertex there and later undo the translation), the bisector is just the geometric mean of the arms of the angle
sqrt(z1 * z2)
Along with stereographic transform and its inverse you can do a lot.
This is directly related to the field of algebraic numbers.
With complex numbers you get translations, scaled rotations and reflections. Sufficient for Euclidean geometry.
1 days ago [-]
20k 1 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
et1337 1 days ago [-]
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.
20k 22 hours ago [-]
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
xbar 1 days ago [-]
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?
waffletower 1 days ago [-]
You can definitely handle camera rotation via vector operations on rotation matrices.
nwallin 21 hours ago [-]
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.
newsoftheday 1 days ago [-]
> 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.
ryandrake 1 days ago [-]
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.
lupire 3 hours ago [-]
This is how most physics/graphics engines work.
GistNoesis 1 days ago [-]
I think it boils down to the alternate view of rotations as two successive reflections.
You can then use householder matrix to avoid trigonometry.
These geometric math tricks are sometimes useful for efficient computations.
For example you can improve Vector-Quantization Variational AutoEncoder (VQ-VAE) using a rotation trick, and compute it efficiently without trigonometry using Householder matrix to find the optimal rotation which map one vector to the other. See section 4.2 of [1]
The question why would someone avoid trigonometry instead of looking toward it is another one. Trigonometry [2] is related to the study of the triangles and connect it naturally to the notion of rotation.
Rotations [3] are a very rich concept related to exponentiation (Multiplication is repeated addition, Exponentiation is repeated multiplication).
As doing things repeatedly tend to diverge, rotations are self stabilizing, which makes them good candidates as building blocks for the universe [4].
Because those operations are non commutative, tremendous complexity emerge just from the order in which the simple operations are repeated, yet it's stable by construction [5][6]
citing the Wikipedia page for trigonometry makes this feel a lot like you just told an LLM the expected comment format and told it to write insightful comments
GistNoesis 1 days ago [-]
I had to check the precise definition for trigonometry while writing my comment, found it interesting so I added a reference.
As with many subject that we learn early in school, it's often interesting revisiting them as adult to perceive additional layer of depth by casting a new look.
With trigonometry we tend to associate it with circle. But fundamentally it's the study of tri-angles.
What is interesting is that the whole theory is "relative". I would reference the wikipedia page for angle but it may make me look like an LLM. The triangle doesn't have positions and orientation baked-in, what matters is the length of the sides and the angle between them.
The theory by definition becomes translation and rotation invariant. And from this symmetry emerge the concept of rotations.
What is also interesting about the concept of angle is that it is a scalar whereas the original objects like lines live in an higher dimension. To avoid losing information you therefore need multiple of these scalars to fully describe the scene.
But there is a degree of redundancy because the angles of a triangle sums to pi. And from this degree of freedom results multiple paths to do the computations. But with this liberty comes the risks of not making progress and going in circles. Also it's harder to see if two points coming from different paths are the same or not, and that's why you have "identities".
Often for doing the computation it's useful to break the symmetry, by picking a center, even though all points could be centers, (but you pick one and that has made all the difference).
Similar situation arise in Elliptic Curve Cryptography, where all points could have the same role, but you pick one as your generator. Also in physics the concept of gauge invariance.
Ok, this is very interesting, as after pondering my code and the article's main pt, I independently came to the same conclusion that angles are what introduces trig. I agree that maybe people might be using angles as intermediates, but IMO there are cases where they're the most realistic abstraction. For example, how can I map a user's mouse movements, or button presses to a change in rotation without a scalar value? Without trig?
User moves cursor or stick a number of pixels/units. User holds key for a number of ms. This is a scalar: An integer or floating point. I pose this to the trig-avoiders: How do I introduce a scalar value into a system of vectors and matrices or quaternions?
a_e_k 1 days ago [-]
My take as a graphics programmer is that angles are perfectly fine as inputs. Bring 'em! And we'll use the trig to turn those into matrices/quaternions/whatever to do the linear algebra. Not a problem.
I'm a trig-avoider too, but see it more as about not wiggling back and forth. You don't want to be computing angle -> linear algebra -> angle -> linear algebra... (I.e., once you've computed derived values from angles, you can usually stay in the derived values realm.)
Pro-tip I once learned from Eric Haines (https://erich.realtimerendering.com/) at a conference: angles should be represented in degrees until you have to convert them to radians to do the trig. That way, user-friendly angles like 90, 45, 30, 60, 180 are all exact and you can add and subtract and multiply them without floating-point drift. I.e., 90.0f is exactly representable in FP32, pi/2 is not. 1000 full revolutions of 360.0f degrees is exact, 1000 full revolutions of float(2*pi) is not.
the__alchemist 1 days ago [-]
Hah. I think we're and the author of both articles on the same page about this. (I had to review my implementations to be sure). I'm a fan of all angles are radians for consistency, and it's more intuitive to me. I.e. a full rot is τ. 1/2 rot is 1/2 τ etc. Pi is standard but makes me do extra mental math, and degrees has the risk of mixing up units, and doesn't have that neat rotation mapping.
Very good tip about the degrees mapping neatly to fp... I had not considered that in my reasoning.
adrian_b 11 hours ago [-]
If you want consistency, you should measure all angles in cycles, not in radians.
Degrees are better than radians, but usually they lead to more complications than using consistently only cycles as the unit of measure for angles (i.e. to plenty of unnecessary multiplications or divisions, the only advantage of degrees of being able to express exactly the angle of 30 degrees and its multiples is not worth in comparison with the disadvantages).
The use of radians introduces additional rounding errors that can be great at each trigonometric function evaluation, and it also wastes time. When the angles are measured in cycles, the reduction of the input range for the function arguments is done exactly and very fast (by just taking the fractional part), unlike with the case when angles are measured in radians.
The use of radians is useful only for certain problems that are solved symbolically with pen on paper, because the use of radians removes the proportionality constant from the integration and derivation formulae for trigonometric function. However this is a mistake, because those formulae are applied seldom, while the use of radians does not eliminate the proportionality constant (2*Pi), but it moves the constant into each function evaluation, with much worse overhead.
Because of this, even in the 19th century, when the use of radians became widespread for symbolic computations, whenever they did numeric computations, not symbolic, the same authors used sexagesimal degrees, not radians.
The use of radians with digital computers has always been a mistake, caused by people who have been taught in school to use radians, because there they were doing mostly symbolic computations, not numeric, and they have passed this habit to computer programs, without ever questioning whether this is the appropriate method for numeric computations.
9 hours ago [-]
the__alchemist 9 hours ago [-]
Holy shit I have to try this.
adrian_b 5 hours ago [-]
Unfortunately, IEEE Std 754 contains a huge mistake, which has been followed by some standard libraries for programming languages.
As an alternative to the trigonometric functions with arguments measured in radians, it recommends a set of functions with arguments measured in half-cycles: sinPi, cosPi, atanPi, atan2Pi and so on.
I do not who is guilty for this, because I have never ever encountered a case when you want to measure angles in half-cycles. There are cases when it would be more convenient to measure angles in right angles (i.e. quarters of a cycle), but half-cycles are always worse than both cycles and right angles. An example where measuring angles in cycles is optimal is when you deal with Fourier series or Fourier transforms. When the unit is the cycle that deletes a proportionality constant from the Fourier formulae, and that constant is always present when any other unit is used, e.g. the radian, the degree or the half-cycle.
Due to this mistake in the standard, it is more likely to find a standard library that includes these functions with angles measured in half-cycles than a library with the corresponding functions for cycles. Half-cycles are still better than radians, by producing more accurate results and being faster, but it may be hard to avoid some scalings by two. However, usually it is not necessary to do a scaling at every invocation, but there are chances that the scalings can be moved outside of loops.
Such functions written for angles measured in half-cycles can be easily modified to work with arguments measured in cycles, but if one does not want to touch a standard library, they may be used as they are.
When one uses consistently the cycle as the unit of angle, which is consistent with measuring frequencies in Hertz, i.e. cycle per second, instead of measuring them in radian per second, one must pay attention to the fact that a lot of formulae from most handbooks of physics are incorrect. Despite the claim that those formulae are written in a form that is independent of the system of units, this claim is false because many formulae are written in a form that is valid only when the unit of angle is the radian.
For example, all formulae for quantities related to rotation movements, as they are written in modern handbooks contain the "radius". This use of the "radius" creates a wrong mental model of the rotational quantities, both for students and also even for many experienced physicists.
In reality, in all those formulae, e.g. in the definition of the angular momentum, in order to obtain the correct formulae one must replace the "radius" with the inverse of the curvature of the trajectory of the movement. Thus the angular momentum is not the product of the linear momentum by the radius, but it is the ratio between the linear momentum and the curvature.
Then one must use the correct definition for the curvature. Most handbooks define the curvature as the inverse of the radius. This is a wrong definition, which is based on the non-explicit assumption that angles are measured in radians.
The correct definition of the curvature is as the ratio between rotation angle and length, for the movement, i.e. more precisely it is the derivative of the rotation angle as a function of the length of the curve on which something moves. When angles are measured in radians, the curvature is the inverse of the radius. When angles are measured in cycles, the curvature is the inverse of the perimeter. Thus with angles measured in cycles the angular momentum is defined as the product between the linear momentum and perimeter. Similarly for the other rotational quantities, like angular velocity and acceleration, moment of inertia and so on.
donkeybeer 12 hours ago [-]
Then why restrict to arbitrary degrees, might as well use 1/2**31sts of the circle. Or a larger higly composite number if you want your 3's and 5's.
adrian_b 11 hours ago [-]
There are many applications where instead of angles it is more convenient to use the Y to X ratio (also the Z to X ratio in 3D), i.e. to use the tangent of the angle as a scalar that encodes the direction.
In 2D, using either the angle or its tangent needs a single number. The third alternative is, as others have mentioned, to use a complex number (i.e. the cos and sin couple).
Any of these 3 (angle, tangent of angle and complex number) may be the best choice for a given problem, but for 2D graphics applications I think that using a complex number is more frequently the best. For 3D problems there are 3 corresponding alternatives, using a pair of angles, using a pair of tangents (i.e. coordinate ratios) or using a quaternion.
Specifying directions by the ratio between increments in orthogonal directions, instead of using angular measures, has always been frequent in engineering, since the Antiquity until today.
For something like cursor movement, the ratio between Y pixels and X pixels clearly seems as the most convenient means to describe the direction of movement.
srean 9 hours ago [-]
That's right. However, one disadvantage of using the tan value (the y/x ratio) over that of (cos,sin) tuple is that the former loses information on whether the y coordinates or the x coordinate was negative.
So, if you use the tan representation you have to carry that information separately. Furthermore, the code needs to correctly handle zero and infinity.
Tan of the half angle takes care of the first problem and is related to the stereographic transform. This works modulo one full rotation.
srean 5 hours ago [-]
It is also revealing that in Fourier series, the phase angle is represented as a sin, cos tuple and not as a scalar.
Karliss 1 days ago [-]
The article answers to this near the very beginning.
> Now, don't get me wrong. Trigonometry is convenient and necessary for data input and for feeding the larger algorithm. What's wrong is when angles and trigonometry suddenly emerge deep in the internals of a 3D engine or algorithm out of nowhere.
In most cases it is perfectly fine to store and clamp your first person view camera angles as angles (unless you are working on 6dof game). That's surface level input data not deep internals of 3d engine. You process your input, convert it to relevant vectors/matrices and only then you forget about angles. You will have at most few dozen such interactive inputs from user with well defined ranges and behavior. It's neither a problem from edge case handling perspective nor performance.
The point isn't to avoid trig for the sake of avoiding it at all cost. It's about not introducing it in situations where it's unnecessary and redundant.
the__alchemist 1 days ago [-]
Ah you're right! Then I believe the author and I are indeed on the same page.
aap_ 1 days ago [-]
He's still computing cross(z, d) and dot(z, d) separately. that looks like a code smell to me. with quaternions this would be easier: just calculate the quotient between z and d and take the square root (which means adding 1 and renormalising). the square root is necessary if one is dealing with vectors, which live in a kind of square-y space. finding the rotation between two spinors is even simpler: it's just the quotient of the the spinors as quaternions. unfortunately hamilton's view that quaternions are the quotient of vectors has never been quite abandoned. it's much more natural to think of them as quotients of spinors.
ajkjk 1 days ago [-]
the dot/cross product are the same operation but expanded into coordinates. Maybe the quaternion (/geometric algebra) version is more compact but it's not like it's a different set of computations. Whereas their removal of the trig functions actually does skip a bunch of unnecessary steps.
BenoitP 1 days ago [-]
> He's still computing cross(z, d) and dot(z, d) separately. that looks like a code smell to me. with quaternions ...
Fair point, but I think you misspelled Projective Geometric Algebra
aap_ 1 days ago [-]
If you only care about rotations in 3d, quaternions do everything you need :) with all the added benefits of having a division algebra to play with (after all the cross product is a division-algebraic operation). PGA is absolutely great, but quite a bit more complex mathematically, and its spinors are not as obvious as quaternionic ones. in addition GA is commonly taught in a very vector-brained way, but i find spinors much easier to deal with.
dxuh 1 days ago [-]
I agree that use of trigonometry is almost always a smell, but e.g. in games there are so many cases where angles are just more useful and intuitive. I just grep-ed for "angle" in a game of mine and I find it for orienting billboard particles (esp. for particles a single angle is much better than a quat for example). Also for an FPS camera controller. It's much simpler to just store a pitch and a yaw and change that with mouse movement, than storing a quat. You can't really look at a quat and know what kind of rotation it represents without opening a calculator. And I also use it for angle "fudging" so if you want to interact with something if you are roughly looking at it, you need to configure an angle range that should be allowed. It just makes sense to configure this as an angle, because we have some intuition for angles. So I guess for computations angles are probably usually wrong, but they are great for intuition (they are low-dimensional and linear in amount of rotation). That makes them a better human interface for rotations. And as soon as you computations start with angles, of course they find their way into the rest of the code.
hrmtst93837 1 days ago [-]
Storing pitch and yaw breaks down once you want arbitrary camera rolls, or if you need to interpolate between orientations, because of gimbal lock. Using angles for small UI bits or flat objects is fine, but when those billboard particles need more than one axis of freedom, you usually end up needing quats anyway. Quats are opaque, but conversion functions and debug views help when you actually need to read what's going on. Trig shortcuts mostly pay off for simple or highly constrained motion, but scaling them up tends to introduce messy edge cases.
nananana9 1 days ago [-]
I'd pretty much always store pitch/yaw for a first/third person controller. This makes it trivial to modify the values in response to input - `pitch += mouse_delta.y` and to clamp the pitch to a sane range (-90 to 90 deg) afterwards.
You can then calculate a quaternion from the pitch/yaw and do whatever additional transforms you wish (e.g. temporary rotation for recoil, or roll when peeking around a corner).
the__alchemist 1 days ago [-]
Interesting. I do it in quaternion, but mostly work in unclamped 6DOF systems.
bob1029 1 days ago [-]
Quaternions break down for other situations. They cannot represent a rotation greater than 360 degrees. In an engine like Unity (which stores rotation as quats), you can use arbitrary Euler angles in the editor and it will work fine, but the scene file has to store 2 things. There is an additional m_LocalEulerAnglesHint property that covers this edge case.
the__alchemist 1 days ago [-]
You're right that quaternions don't work for those. Vec3 is the move IMO. Direction is axis; len is magnitude.
eska 1 days ago [-]
Now, don't get me wrong. Trigonometry is convenient and necessary for data input and for feeding the larger algorithm.
cmovq 1 days ago [-]
For a graphics programmer acos(dot(x, y)) always raises an eyebrow. Since most of the time you actually want cos(theta) and even when you think you need the angle you probably don’t.
the__alchemist 1 days ago [-]
I think this is more subjective than the author makes it out to be. I take a third approach: You can change out Matrices for Quaternions. Then do almost every operation using these two types, and a few operation between them. The operation implementations are a mix of dot products, quaternion multiplication, trig etc.
I find this flow works well because it's like building arbitrarily complex transformation by composing a few operations, so easy to keep in my head. Or maybe I just got used to it, and the key is find a stick with a pattern you're effective with.
So:
> For example, you are aligning a spaceship to an animation path, by making sure the spaceship's z axis aligns with the path's tangent or direction vector d.
Might be:
let ship_z = ship.orientation.rotate_vec(Z_AXIS);
let rotator = Quaternion::from_unit_vecs(ship_z.to_normalized(), path.to_normalized());
ship.orientation *= rotator;
I should break this down into individual interoperations to compare this to the two examples in the article. To start, `from_unit_vecs` is based on the cross product, and `rotate_vec` is based on quaternion-vector multiplication. So no trig there. But `quaternion::from_axis_angle()` uses sin and cos.
I need to review for the sort of redundant operations it warns about, but from a skim, I'm only using acos for SLERP, and computing dihedral angles, which aren't really the basic building blocks. Not using atan. So maybe OK?
edit: Insight: It appears the use of trig in my code is exclusively for when an angle is part of the concept. If something is only vectors and quaternions, it stays that way. If an angle is introduced, trig occurs. And to the article: For that spaceship alignment example, it doesn't introduce an angle, so no trig. But there are many cases IMO where you want an explicit angle (Think user interactions)
the__alchemist 1 days ago [-]
Update with the big picture: I think the rotationAxisAngle example in the article is fine. The problem isn't that it exists and uses angles/trig: There are legit uses for that function! The problem is that it's not the best tool for aligning the spaceship. So: Problem is not that fn or angles/trig: It's using the wrong tool.
aleph_minus_one 1 days ago [-]
> You can change out Matrices for Quaternions.
Better use spin groups: they work in every dimension.
the__alchemist 1 days ago [-]
Hah! We can throw bivectors onto the pile too for the fans!
don-bright 13 hours ago [-]
The other thing it can give you is computationally exact results since rationals are closed over division. Sine is interesting because where the input is rational the output is almost always irrational and where the output is rational the input is almost always irrational. In computation the first time you use sine in a program you have injected approximation. If you want to build things like reproducible code and geometric caching it can be interesting to compare using a purely rational computation system to an approximative system.
adrian_b 11 hours ago [-]
The trigonometric functions need not inject worse approximations than division.
If you compute trigonometric functions where the arguments are binary floating-point numbers and you measure the angles in cycles, not in radians (using radians is always a huge mistake in my opinion), the results can be expressed exactly using rational operations and the sqrt function.
You could compute them symbolically and use such symbolic expressions for exact computation, like you use rational numbers.
If you compute them numerically, computing a sqrt does not need more time than a division and correct rounding or computing an arbitrary number of digits are also not more difficult than for division.
Of course, you typically do not care about this, so you can just compute the trigonometric functions approximately, like you also do with division and sqrt, and in a similar time.
simonreiff 1 days ago [-]
Nice article! I'm not a graphics programmer but mathematically it makes full sense that cross-product would be a vast optimization over using `sin()`. From a complexity perspective, the computation of a cross-product reduces to calculating a formal determinant, a fixed number of arithmetic operations, and hence resolves to O(1) complexity. By contrast, computing `sin()` is O(M(n)log(n)) (even though faster algorithms are often possible in practice). See Brent, Fast multiple-precision evaluation of elementary functions (1976).
mistivia 19 hours ago [-]
> we are performing an rather imprecise and expensive acos() call
No, the acos() call is not expensive at all. There is hardware acceleration.We can calculate acos() with in 12 CPU instructions.
I don't disagree with the "use linear algebra" assertion the author makes.
The most impressive math I've seen done during a real-time technical conversation was by someone leveraging comprehensive command of trig identities.
storus 1 days ago [-]
In principle, wouldn't a change of basis be all that is needed?
srean 1 days ago [-]
It's a little more than change of basis, although change of basis is an important part of it. It converts many apparently trigonometric operations into algebraic ones, root finding included.
There are certain drawbacks. If the solution involves non-algebraic numbers there is no getting away from the transcendental numbers (that ultimately get approximated by algebraic numbers).
This is avoiding an common but unnecesary round trip. When your inputs are vectors, angles are an unnecessary intermediate representation. You can substitute the geometric meaning of dot and cross product directly into the Rodrigues matrix and get by with less operations overall. It's more elegant, uses less instructions.
xeonmc 21 hours ago [-]
That’s exactly what I mean, there are no inverse trig that needs to be involved anywhere, see the matrix section in the article. It is trivial to recognize that vector inputs are pretty much the same space the k coefficients and mentally treat cos and sin as a shorthand symbol in terms of vector products.
And in any case inverse trig functions are just components of logarithms of quaternions, and trig is components of exponentiating half-axis-angle into quaternions.
skrebbel 1 days ago [-]
The point isn't that formula, it's that using angles for parameters or intermediary values is often wasteful.
ajkjk 1 days ago [-]
It is not.
rprenger 1 days ago [-]
Also, while we're getting rid of angles, can we please get rid of cross products and just use geometric algebra tools?
virgil_disgr4ce 1 days ago [-]
OK I have a genuine question outside the topic of TFA. Do people really prefer "orientate" over "orient"? This pattern baffles me. You don't get out of the subway and "orientate" yourself, you "orient" yourself.
I mean I'm perfectly aware that language is a descriptive cultural process etc etc but man this bugs the crap out of me for some reason
nyeah 1 days ago [-]
I think Americans tend to say "orient." I think English people tend to say "orientate."
kevin_thibedeau 1 days ago [-]
I vote for "eastify".
adrian_b 12 hours ago [-]
Orient means "rising", so it can be used as an abbreviation when referring to the direction of the rising Sun.
Occident means "falling", so it can be used as an abbreviation when referring to the direction of the falling Sun.
"Orientate" is more correct etymologically to be used as a verb than "orient" ("rising"), and it comes from an expression that described how something is raised towards a certain direction.
I think that the reason why the verb "orient" has come to be preferred by some was that "orientated" seemed like a mouthful, so it was abbreviated to "oriented", whence a verb "orient" has been back-formed.
The guilty for "orientated" being so long is the habit of English of making verbs from Latin passive participles, instead of using just the verb stems, which leads to long verbal words and to clumsy English past participles derived from them. Latin also derived new verbal stems from passive participles, but those had a different meaning than the base verbal stem, being either frequentative or causative, so the extra length of such words was justified.
moi2388 1 days ago [-]
I absolutely get out of the subway and orientate myself.
If I orient myself I have not taken the subway but the orient express, I’m afraid..
yobert 1 days ago [-]
When I get out of the subway, I always occident myself.
It eschews angles entirely, sticking to ratios. It avoids square roots by sticking to "quadrances" (squared distance; i.e. pythagoras/euclidean-distance without taking square roots).
I highly recommend Wildberger's extensive Youtube channels too https://www.youtube.com/@njwildberger and https://www.youtube.com/@WildEggmathematicscourses
He's quite contrarian, so I'd take his informal statements with a pinch of salt (e.g. that there's no such thing as Real numbers; the underlying argument is reasonable, but the grand statements lose all that nuance); but he ends up approaching many subjects from an interesting perspective, and presents lots of nice connections e.g. between projective geometry, linear algebra, etc.
The axioms were not handed to us from above. They were a product of a thought process anchored to intuition about the real world. The outcomes of that process can be argued about. This includes the belief that the outcomes are wrong even if we can't point to any obvious paradox.
If you can derive a contradiction using his methods of computation I would study that with interest.
By "sound" I do not mean provably sound. I mean I have not seen a proof of unsoundness yet.
“Sound” != proof of soundness in the same way that the Riemann Hypothesis being true is not the same as RH being proven.
Gödel wept.
An undecidable proposition is neither true nor false, it is not both true and false.
A system with undecidable propositions may be perfectly fine, while a contradictory system is useless.
Thus what the previous poster has said has nothing to do with what Gödel had proved.
Ensuring that the system of axioms that you use is non-contradictory has remained as useful today as by the time of Euclid and basing your reasoning on clearly stated non-contradictory axioms has also remained equally important, even if we are now aware that there may be undecidable things (which are normally irrelevant in practice anyway).
The results of Gödel may be interpreted as a demonstration that the use of ternary logic is unavoidable in mathematics, like it already was in real life, where it cannot always be determined whether a claim is true or false.
There are two well accepted definitions of soundness. One of them is the inability to prove true == false, that is, one cannot prove a contradiction from within that axiomatic system.
Indeed, as you allude, you cannot have both in an expressive enough system.
Can you elaborate on this? I think many understand that the "existence of some object" implies there is some semantic difference even if there isn't a practical one.
I really enjoyed Wildberger's take back in high school and college. It can be far more intuitive to avoid unnecessary invocation of calculation and abstraction when possible.
I think the main thrust of his argument was that if we're going to give in to notions of infinity, irrationals, etc. it should be when they're truly needed. Most students are being given the opposite (as early as possible and with bad examples) to suit the limited time given in school. He then asks if/where we really need them at all, and has yet to be answered convincingly enough (probably only because nobody cares).
I wholeheartedly agree with the point being made in the post. I had commented about this in the recent asin() post but deleted thinking it might not be of general interest.
If you care about angles and rotations in the plane, it is often profitable to represent an angle not by a scalar such as a degree or a radian but as a tuple
or as a complex number.This way one can often avoid calls to expensive trigonometric functions. One may need calls to square roots and general polynomial root finding.
In Python you can represent an angle as a unit complex numbers and the runtime will do the computations for you.
For example, if you needed the angular bisector of an angle subtended at the origin (you can translate the vertex there and later undo the translation), the bisector is just the geometric mean of the arms of the angle
Along with stereographic transform and its inverse you can do a lot.This is directly related to the field of algebraic numbers.
With complex numbers you get translations, scaled rotations and reflections. Sufficient for Euclidean geometry.
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
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.
Have you ended up with a set of self-implemented tools that you reuse?
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.
Agreed. In my view, the method the author figured out is far from intuitive for the general population, including me.
You can then use householder matrix to avoid trigonometry.
These geometric math tricks are sometimes useful for efficient computations.
For example you can improve Vector-Quantization Variational AutoEncoder (VQ-VAE) using a rotation trick, and compute it efficiently without trigonometry using Householder matrix to find the optimal rotation which map one vector to the other. See section 4.2 of [1]
The question why would someone avoid trigonometry instead of looking toward it is another one. Trigonometry [2] is related to the study of the triangles and connect it naturally to the notion of rotation.
Rotations [3] are a very rich concept related to exponentiation (Multiplication is repeated addition, Exponentiation is repeated multiplication).
As doing things repeatedly tend to diverge, rotations are self stabilizing, which makes them good candidates as building blocks for the universe [4].
Because those operations are non commutative, tremendous complexity emerge just from the order in which the simple operations are repeated, yet it's stable by construction [5][6]
[0]https://en.wikipedia.org/wiki/Householder_transformation
[1]https://arxiv.org/abs/2410.06424
[2]https://en.wikipedia.org/wiki/Trigonometry
[3]https://en.wikipedia.org/wiki/Matrix_exponential
[4]https://en.wikipedia.org/wiki/Exponential_map_(Lie_theory)
[5]https://en.wikipedia.org/wiki/Geometric_algebra
[6]https://en.wikipedia.org/wiki/Clifford_algebra
As with many subject that we learn early in school, it's often interesting revisiting them as adult to perceive additional layer of depth by casting a new look.
With trigonometry we tend to associate it with circle. But fundamentally it's the study of tri-angles.
What is interesting is that the whole theory is "relative". I would reference the wikipedia page for angle but it may make me look like an LLM. The triangle doesn't have positions and orientation baked-in, what matters is the length of the sides and the angle between them.
The theory by definition becomes translation and rotation invariant. And from this symmetry emerge the concept of rotations.
What is also interesting about the concept of angle is that it is a scalar whereas the original objects like lines live in an higher dimension. To avoid losing information you therefore need multiple of these scalars to fully describe the scene.
But there is a degree of redundancy because the angles of a triangle sums to pi. And from this degree of freedom results multiple paths to do the computations. But with this liberty comes the risks of not making progress and going in circles. Also it's harder to see if two points coming from different paths are the same or not, and that's why you have "identities".
Often for doing the computation it's useful to break the symmetry, by picking a center, even though all points could be centers, (but you pick one and that has made all the difference).
Similar situation arise in Elliptic Curve Cryptography, where all points could have the same role, but you pick one as your generator. Also in physics the concept of gauge invariance.
User moves cursor or stick a number of pixels/units. User holds key for a number of ms. This is a scalar: An integer or floating point. I pose this to the trig-avoiders: How do I introduce a scalar value into a system of vectors and matrices or quaternions?
I'm a trig-avoider too, but see it more as about not wiggling back and forth. You don't want to be computing angle -> linear algebra -> angle -> linear algebra... (I.e., once you've computed derived values from angles, you can usually stay in the derived values realm.)
Pro-tip I once learned from Eric Haines (https://erich.realtimerendering.com/) at a conference: angles should be represented in degrees until you have to convert them to radians to do the trig. That way, user-friendly angles like 90, 45, 30, 60, 180 are all exact and you can add and subtract and multiply them without floating-point drift. I.e., 90.0f is exactly representable in FP32, pi/2 is not. 1000 full revolutions of 360.0f degrees is exact, 1000 full revolutions of float(2*pi) is not.
Very good tip about the degrees mapping neatly to fp... I had not considered that in my reasoning.
Degrees are better than radians, but usually they lead to more complications than using consistently only cycles as the unit of measure for angles (i.e. to plenty of unnecessary multiplications or divisions, the only advantage of degrees of being able to express exactly the angle of 30 degrees and its multiples is not worth in comparison with the disadvantages).
The use of radians introduces additional rounding errors that can be great at each trigonometric function evaluation, and it also wastes time. When the angles are measured in cycles, the reduction of the input range for the function arguments is done exactly and very fast (by just taking the fractional part), unlike with the case when angles are measured in radians.
The use of radians is useful only for certain problems that are solved symbolically with pen on paper, because the use of radians removes the proportionality constant from the integration and derivation formulae for trigonometric function. However this is a mistake, because those formulae are applied seldom, while the use of radians does not eliminate the proportionality constant (2*Pi), but it moves the constant into each function evaluation, with much worse overhead.
Because of this, even in the 19th century, when the use of radians became widespread for symbolic computations, whenever they did numeric computations, not symbolic, the same authors used sexagesimal degrees, not radians.
The use of radians with digital computers has always been a mistake, caused by people who have been taught in school to use radians, because there they were doing mostly symbolic computations, not numeric, and they have passed this habit to computer programs, without ever questioning whether this is the appropriate method for numeric computations.
As an alternative to the trigonometric functions with arguments measured in radians, it recommends a set of functions with arguments measured in half-cycles: sinPi, cosPi, atanPi, atan2Pi and so on.
I do not who is guilty for this, because I have never ever encountered a case when you want to measure angles in half-cycles. There are cases when it would be more convenient to measure angles in right angles (i.e. quarters of a cycle), but half-cycles are always worse than both cycles and right angles. An example where measuring angles in cycles is optimal is when you deal with Fourier series or Fourier transforms. When the unit is the cycle that deletes a proportionality constant from the Fourier formulae, and that constant is always present when any other unit is used, e.g. the radian, the degree or the half-cycle.
Due to this mistake in the standard, it is more likely to find a standard library that includes these functions with angles measured in half-cycles than a library with the corresponding functions for cycles. Half-cycles are still better than radians, by producing more accurate results and being faster, but it may be hard to avoid some scalings by two. However, usually it is not necessary to do a scaling at every invocation, but there are chances that the scalings can be moved outside of loops.
Such functions written for angles measured in half-cycles can be easily modified to work with arguments measured in cycles, but if one does not want to touch a standard library, they may be used as they are.
When one uses consistently the cycle as the unit of angle, which is consistent with measuring frequencies in Hertz, i.e. cycle per second, instead of measuring them in radian per second, one must pay attention to the fact that a lot of formulae from most handbooks of physics are incorrect. Despite the claim that those formulae are written in a form that is independent of the system of units, this claim is false because many formulae are written in a form that is valid only when the unit of angle is the radian.
For example, all formulae for quantities related to rotation movements, as they are written in modern handbooks contain the "radius". This use of the "radius" creates a wrong mental model of the rotational quantities, both for students and also even for many experienced physicists.
In reality, in all those formulae, e.g. in the definition of the angular momentum, in order to obtain the correct formulae one must replace the "radius" with the inverse of the curvature of the trajectory of the movement. Thus the angular momentum is not the product of the linear momentum by the radius, but it is the ratio between the linear momentum and the curvature.
Then one must use the correct definition for the curvature. Most handbooks define the curvature as the inverse of the radius. This is a wrong definition, which is based on the non-explicit assumption that angles are measured in radians.
The correct definition of the curvature is as the ratio between rotation angle and length, for the movement, i.e. more precisely it is the derivative of the rotation angle as a function of the length of the curve on which something moves. When angles are measured in radians, the curvature is the inverse of the radius. When angles are measured in cycles, the curvature is the inverse of the perimeter. Thus with angles measured in cycles the angular momentum is defined as the product between the linear momentum and perimeter. Similarly for the other rotational quantities, like angular velocity and acceleration, moment of inertia and so on.
In 2D, using either the angle or its tangent needs a single number. The third alternative is, as others have mentioned, to use a complex number (i.e. the cos and sin couple).
Any of these 3 (angle, tangent of angle and complex number) may be the best choice for a given problem, but for 2D graphics applications I think that using a complex number is more frequently the best. For 3D problems there are 3 corresponding alternatives, using a pair of angles, using a pair of tangents (i.e. coordinate ratios) or using a quaternion.
Specifying directions by the ratio between increments in orthogonal directions, instead of using angular measures, has always been frequent in engineering, since the Antiquity until today.
For something like cursor movement, the ratio between Y pixels and X pixels clearly seems as the most convenient means to describe the direction of movement.
So, if you use the tan representation you have to carry that information separately. Furthermore, the code needs to correctly handle zero and infinity.
Tan of the half angle takes care of the first problem and is related to the stereographic transform. This works modulo one full rotation.
> Now, don't get me wrong. Trigonometry is convenient and necessary for data input and for feeding the larger algorithm. What's wrong is when angles and trigonometry suddenly emerge deep in the internals of a 3D engine or algorithm out of nowhere.
In most cases it is perfectly fine to store and clamp your first person view camera angles as angles (unless you are working on 6dof game). That's surface level input data not deep internals of 3d engine. You process your input, convert it to relevant vectors/matrices and only then you forget about angles. You will have at most few dozen such interactive inputs from user with well defined ranges and behavior. It's neither a problem from edge case handling perspective nor performance.
The point isn't to avoid trig for the sake of avoiding it at all cost. It's about not introducing it in situations where it's unnecessary and redundant.
Fair point, but I think you misspelled Projective Geometric Algebra
You can then calculate a quaternion from the pitch/yaw and do whatever additional transforms you wish (e.g. temporary rotation for recoil, or roll when peeking around a corner).
I find this flow works well because it's like building arbitrarily complex transformation by composing a few operations, so easy to keep in my head. Or maybe I just got used to it, and the key is find a stick with a pattern you're effective with.
So:
> For example, you are aligning a spaceship to an animation path, by making sure the spaceship's z axis aligns with the path's tangent or direction vector d.
Might be:
I should break this down into individual interoperations to compare this to the two examples in the article. To start, `from_unit_vecs` is based on the cross product, and `rotate_vec` is based on quaternion-vector multiplication. So no trig there. But `quaternion::from_axis_angle()` uses sin and cos.I need to review for the sort of redundant operations it warns about, but from a skim, I'm only using acos for SLERP, and computing dihedral angles, which aren't really the basic building blocks. Not using atan. So maybe OK?
edit: Insight: It appears the use of trig in my code is exclusively for when an angle is part of the concept. If something is only vectors and quaternions, it stays that way. If an angle is introduced, trig occurs. And to the article: For that spaceship alignment example, it doesn't introduce an angle, so no trig. But there are many cases IMO where you want an explicit angle (Think user interactions)
Better use spin groups: they work in every dimension.
If you compute trigonometric functions where the arguments are binary floating-point numbers and you measure the angles in cycles, not in radians (using radians is always a huge mistake in my opinion), the results can be expressed exactly using rational operations and the sqrt function.
You could compute them symbolically and use such symbolic expressions for exact computation, like you use rational numbers.
If you compute them numerically, computing a sqrt does not need more time than a division and correct rounding or computing an arbitrary number of digits are also not more difficult than for division.
Of course, you typically do not care about this, so you can just compute the trigonometric functions approximately, like you also do with division and sqrt, and in a similar time.
No, the acos() call is not expensive at all. There is hardware acceleration.We can calculate acos() with in 12 CPU instructions.
https://git.musl-libc.org/cgit/musl/tree/src/math/i386/acos....
The most impressive math I've seen done during a real-time technical conversation was by someone leveraging comprehensive command of trig identities.
There are certain drawbacks. If the solution involves non-algebraic numbers there is no getting away from the transcendental numbers (that ultimately get approximated by algebraic numbers).
And in any case inverse trig functions are just components of logarithms of quaternions, and trig is components of exponentiating half-axis-angle into quaternions.
I mean I'm perfectly aware that language is a descriptive cultural process etc etc but man this bugs the crap out of me for some reason
Occident means "falling", so it can be used as an abbreviation when referring to the direction of the falling Sun.
"Orientate" is more correct etymologically to be used as a verb than "orient" ("rising"), and it comes from an expression that described how something is raised towards a certain direction.
I think that the reason why the verb "orient" has come to be preferred by some was that "orientated" seemed like a mouthful, so it was abbreviated to "oriented", whence a verb "orient" has been back-formed.
The guilty for "orientated" being so long is the habit of English of making verbs from Latin passive participles, instead of using just the verb stems, which leads to long verbal words and to clumsy English past participles derived from them. Latin also derived new verbal stems from passive participles, but those had a different meaning than the base verbal stem, being either frequentative or causative, so the extra length of such words was justified.
If I orient myself I have not taken the subway but the orient express, I’m afraid..