fu5ha / ultraviolet

A wide linear algebra crate for games and graphics.
https://crates.io/crates/ultraviolet
745 stars 80 forks source link

`Mul<Bivec3>` implementation for `Mat3` #30

Open Emiluren opened 4 years ago

Emiluren commented 4 years ago

I am currently writing a physics engine (just to learn) and I happened to find ultraviolet while looking for a linear algebra library. I had never heard of geometric algebra before so learning about bivectors and rotors was interesting.

I managed to figure out that torque should probably be represented by a bivector but I ran into a problem when I was going to calculate the angular acceleration. I am assuming that the inverse of the inertia tensor can still be represented by a 3x3 matrix but I noticed that there is no implementation of Mul<Bivec3> for Mat3. Should there be one or am I going about this in the wrong way?

I am also considering using a Bivec3 (which I noticed has an implementation of Mul<Bivec3>) for the inertia tensor but I guess this would only let me have the equivalent of a diagonal matrix.

fu5ha commented 4 years ago

Hmm... Mul<Bivec3> for Mat3 does sound reasonable. Should probably just be the same as for a Vec3.

chakravala commented 4 years ago

Not a user of this language repo, but mathematically speaking, there are two possibilities for interpreting a matrix times a bivector. In one interpretation, you convert the bivector to a vector and do a standard multiply. In the other intepretation, you would think of the matrix as a dyadic tensor (column vectors nested inside a vector), and then use the Grassmann interior product as a tensor contraction.

Maybe there is another way you can think of it also.

mewertd2 commented 4 years ago

If you diagonalize your inertia tensor you don't need a matrix multiply. Haven't thought through what you do with that diagonalized tensor though.

The start of this paper has some info: https://marctenbosch.com/ndphysics/NDrigidbody.pdf Seems they are taking the dual of the angular velocity bivector to get a vector. Then just use a regular matrix/vector multiply with the inertia tensor and convert back to bivector after.

fu5ha commented 4 years ago

@Emiluren just for reference, I posted this issue in a geometric algebra related discord recently as I'm a bit out of my depth (I know next to nothing about physics simulation) and these nice people decided to weigh in... if you read that paper and figure out what it is that you need ultraviolet to do, I'm happy to implement it (or you could yourself if you wish!)

mewertd2 commented 4 years ago

@chakravala and I both pretty much suggested converting from/to bivector to/from vector and doing a matrix multiply with the inertia tensor as the simplest solution. For that I think @termhn you just need a dual method to convert from a vector to and from the bivector isomorphic to it. I didn't see this method here, but I didn't do long search.

dual may not be your preferred name. Conceptually it gives you a scaled blade orthogonal to your input blade.

eric-wieser commented 4 years ago

I don't think you want to take the dual and transform that, that results in the wrong transformation - you'll end up with a transformed bivector not matching the bivector formed from wedging two transformed vectors.

Instead, you should take an outermorphism of the matrix, which in 3d is a matrix with (some permutation of) columns c2 ^ c3, c3^c1, c1^c2 .

hugohadfield commented 4 years ago

I'm with @mewertd2 here, diagonalising the inertia tensor is definitely the way to go, then you are basically just applying a scaling to the components of the bivector. I find a useful way to think about the inertia tensor is as a linear function on the angular velocity that maps it to the angular momentum, the inverse inertia tensor is just the inverse of that function. These functions can be instantiated as matrices and (for 3d vectorspace GA) will come out looking exactly the same as the equivalent standard inertia tensor matrices but with some sign flips and the rows/columns might be in a different order.

If you are after an easy way of calculating the inertia tensor and inverse and applying it to a bivector (and you are using an axis aligned body frame) then take these formulae: https://slides.com/hugohadfield/game2020#/54 and ignore all the t^i and t_i bits. Edit: oh woops saw that is the wrong link, you actually want: [ \Omega_b = M(\dot{Bb}) = m\sum{i=1}^{i=3}\gamma_i(\dot{B_b}\cdot l^i)l_i ] and [ M^{-1}(\Omega_b) = \dot{Bb} = \frac{1}{m}\sum{i=1}^{i=3}\frac{1}{\gamma_i}(\Omega_b\cdot l^i)l_i ]

Emiluren commented 4 years ago

Thank you all for the suggestions! As soon as I have time I'm going to have to see if I can write some code based on this.

T0mstone commented 7 months ago

Hmm... Mul<Bivec3> for Mat3 does sound reasonable. Should probably just be the same as for a Vec3.

No, it probably shouldn't. The natural thing to do here is the outermorphism, i.e. A(u ʌ v) = (Au) ʌ (Av).