Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Show HN: Visualizing the math that powers 3D character animation (diegomacario.github.io)
238 points by diegomacario on June 13, 2022 | hide | past | favorite | 53 comments
Hi everyone! I'm the author of this project. I wrote it because I think that the math that makes characters move in games and movies is incredibly beautiful, and I wanted to give others a glimpse into it.

It's crazy to think that quaternions, an abstract mathematical tool discovered by William Rowan Hamilton in 1843, would be so perfectly suited to solve hard problems in the world of 3D character animation more than a hundred years later. The story of how he discovered quaternions is also beautiful. Here's an excerpt from Wikipedia:

"Hamilton was looking for ways of extending complex numbers (which can be viewed as points on a 2-dimensional Argand diagram) to higher spatial dimensions. In working with four dimensions, rather than three, he created quaternion algebra. According to Hamilton, on 16 October he was out walking along the Royal Canal in Dublin with his wife when the solution in the form of the equation

i2 = j2 = k2 = ijk = −1

occurred to him; Hamilton then carved this equation using his penknife into the side of the nearby Broom Bridge (which Hamilton called Brougham Bridge)."

There's a plaque that commemorates that moment on Broom Bridge now.

If you have any questions about this project, I would love to answer them, but I recommend reading the README first, which should explain everything:

https://github.com/diegomacario/Animation-Magic/blob/main/RE...

Thank you!



On the subject of quaternions, here is an article that pops up on HN from time to time.

https://marctenbosch.com/quaternions/

It is called "Let's remove Quaternions from every 3D Engine". The author suggests replacing quaternions with rotors and geometric algebra. In 3D, the formulas are essentially the same, but framed differently. It makes some "surprising" properties more intuitive and is extensible to any number of dimensions. The last part is especially relevant to the author as he is developing "Miegakure", a 4D game (i.e. the game world has 4 spatial dimensions).


Wow that's fascinating, thanks for sharing it!

Although I disagree with how the author describes quaternions as black boxes. The two questions he asks:

- Why does i2=j2=k2=−1 and ij=k? - Why do we take a vector and upgrade it to an "imaginary" vector in order to transform it, like q(xi+yj+zk)q∗?

Are clearly explained in these interactive videos created by Grant Sanderson and Ben Eater: https://eater.net/quaternions

After I watched those videos, quaternions stopped being so opaque to me. I recommend them :-)


yeah, those videos are opaque, too.

if you already understand quaternions, then they're apparently excellent; everyone who understands quaternions recommends them.

I don't understand quaternions. I do not understand videos which attempt to explain them. I've seen them all a dozen times each.


Although I grokked quaternions before learning GA, I am 100% certain that the GA explanation is better and more intuitive.

GA breaks down quaternions (and their generalization to arbitrary dimensions) into smaller pieces that are much more obvious.

It takes hundreds of years to invent quaternions from scratch, but it takes 10 minutes to invent quaternions from GA.


Given that Miegakure has been “coming soon” for over ten years (maybe the dev initially planned it as a 10-year-game, but if so I wish he would’ve said so when people asked when it was coming) I’m going to suggest putting a hold on deciding whether this way of reckoning rotations results in a better development process.


I don't anyone who took the 4D game concept further than him, there is no "better development process" yet.

And if anything, I don't think the engine is the problem. He already shipped 4D toys, which I suspect is a way to monetize the devtools he made for Miegakure (nothing wrong with that). And even before that, the 4D was fine.

But while it is nice having good 4D, turning it into an entertaining game with good graphics, good puzzle design, a story that doesn't suck (even a simple one), etc... is hard. And we are not talking about a FPS or 2D platformer here, there are no game design books about making games like Miegakure, and there are many, many things that can go wrong. And to be honest, I hope for the best, but I don't expect much.

One big difficulty I see is that not only the designers have to understand 4D to make interesting worlds/puzzles, but the game has to teach that to players too, with the right difficulty curve.


there's a minecraft-style 4d sandbox game, with a playable demo: https://store.steampowered.com/app/1941640/4D_Miner/


Can relate as a person working on a game for 20 years and still considering it unfinished. ) The rotation formula is probably not the case here.


GA is more general than (and superior to) quaternions (the even subalgebra of G3). However, it requires a powerful type system and compiler to compile general GA expressions to something as efficient as quaternions. C++ won't cut it. You might be able to get clever by defining a special numerically indexed type for Gn or its even subalgebras; C++ could probably do that. But it wouldn't be as nice as fully generic GA.


What do you mean by powerful type system and compiler? Do you mean an optimizing compiler that can eliminate the redundant zero terms when multiplying multivectors with many zero grades?


Correct. Quaternions have 4 elements and a small number of multiplications. G3 has 8 elements and more multiplications. This gets worse quickly in higher dimensions.


for general GA yes but for the GA needed to replace quaternions in 3D?

I'm far from good at math but the GA article linked above has this comparision of quaternion code vs rotor (GA) code

https://marctenbosch.com/quaternions/code.htm


Operations in G3 have a bunch of extra work compared to operations on quaternions alone due to the presence of odd grades. However, if your values are quaternionic, these grades should always be zero, so you can safely elide the operations. The compiler just has to be smart enough to see this.

The basis of G3 is 1,x,y,z,xy,xz,yz,xyz. Quaternions only have 1,xy,xz,yz. Quaternion multiplications are closed; xyyz = xz, xyxz = -yz, xzyz = -xy. xyxy=-1. If your compiler is smart enough to figure out that x,y,z,xyz are always zero, you can save the extraneous operations.


Thanks for sharing - have stumbled over the term "geometric algebra" a couple of times, but this article made it click for me.

I completely agree with the sentiment that the algebraic mumbo jumbo often used to introduce quaternions is not very satisfying. Fortunately, as quantum computing becomes a mainstream topic, more people will have to learn about "Rotations on the Bloch sphere" [0] -- and then quaternions and rotations actually make sense.

[0] https://en.wikipedia.org/wiki/Bloch_sphere#Rotations_about_a...


The author also made 4D-Toys which I suppose was a proving ground for the more ambitious game project. If you have PCVR it's a good way to stretch your imagination.


Nice work, but displaying the time evolution of individual quaternion components is about as intuitive of a visualization as displaying the time evolution of an individual pixel to visualize video compression...


Hahaha this is a fair comment. I guess my intention was to show the complex number crunching that happens in the background to make characters move. I'm still thinking about better ways to visualize things.


Could you overlay the graphs with a sort of arrow, indicating the the actual direction the quaternion is pointing in? I had no knowledge on animation before, this was a great primer! Maybe having the graphs sync up could be a toggle - I feel like at low animation speeds, this would help visualize what's going on.


Got it! I think you should also read up on dual quaternions for more mind-blowing math if you haven’t done so yet!


Cool project!

AFAIK many games are using 3x4 bone matrices instead of 4x4. These matrices don't need projection component anyway i.e. 3x4 is enough.

This saves some bandwidth updating the constant buffer with them, also takes slightly less math instructions in the vertex shader.


More importantly one less uniform slot!


hmmm nice optimisation, might borrow that one!


Really cool, thank you. This is the standard way of animating in most engines, right? I'm wondering if there are other techniques that save on sampling the data. Bones form a hierarchy and when the spine bone moves it affects the movement of all the other limbs, but I'm not sure if that's more or less expensive.


Thanks proc0! What you are describing (a hierarchy of bones) is exactly what I'm doing. I decided not to mention that to simplify the explanation of how character animations work, but here are the missing details:

- All the little curves that I'm plotting show the local orientation of each joint.

- To obtain the world orientation of a particular joint, it's necessary to combine the transform matrices of all its parent joints until you reach the root of the hierarchy.

For example, to get the world transform of a wrist joint, you need to combine the local transforms of the wrist, elbow, shoulder, neck, etc. joints.

Animation curves are stored in local space in glTF files, and those are the curves that I'm displaying.

I hope this explains things.


Nice, I was thinking they had absolute coordinates. Thanks for clarifying.


I'm a little confused about why the curves are "sampled" to update the joint transformations: ``` So if we are rendering 60 frames per second, we are basically doing the following 60 times a second:

Sample all the curves you see on the graphs to get the orientation of each joint... ```

When the curves are "sampled", does that mean in a 60 fps animation, there are 60 timestep values t={t1, t2, ... t60} sampled from a uniform distributions, and evaluated at x(t), y(t), z(t), and w(t), and then those values are stepped through sequentially? If that is the case, why not just set t={1/60, 2/60, ... 1}?

Or does "sampling" here just mean function is evaluated at an appropriate t value, and not refering to statistical sampling?



This definition clears up it up nicely for me:

"In signal processing, sampling is the reduction of a continuous-time signal to a discrete-time signal... A sample is a value of the signal at a point in time and/or space; this definition differs from the usage in statistics, which refers to a set of such values."

So it's a sample in the sense a set of (x, y, z, w) values from discrete timesteps represents a continuous timestep, but doesn't require specifying and using random variables to determine those timesteps.


Yes, sampling means ‘reading the value at a particular time’. Same sense as in signal processing.

If everything goes to plan, you are sampling at 1/60, 2/60, etc.

But if the previous frame took a bit longer to render, you might be at a different time. What you want is the value for all of those curves at whatever time it is, not at some fixed time.


Sorry for the confusion. Your second statement is correct. Sampling just means to evaluate the function at an appropriate t value. I will update the README to make this clearer.


Pretty sure it just means evaluated at a finite number of appropriate t values and interpolated to find intermediate values.

I agree that it's definitely an abuse of terminology.


It's a gorgeous visualization, but it appears the UI is bugging out for me on Brave and Safari in MacOS. The layout has no issue, but I can't select any of the dropdowns.


Oh thanks for reporting that dwrodri! Note that the controls don't work on touchscreens yet. If you use a mouse/trackpad and keyboard, you should be able to play with all the settings.


Works for me on safari MacOS even if it feels slow


I recommend running it on Chrome. It runs more smoothly there. I'm still improving the performance on Safari.


Downvote for actually suggesting turning us back into 90s era "Best Viewed In" situation.

I do applaud the wanting to improve performance elsewhere, but still gets a big shake of my head in disappointment that dev is allowed to get to a place where it only works in one browser at first until some amount of work after release to fix to work in other browsers. My sincere hope that you do get it to work universally, realize what was done that made it one-sided to begin with, and avoid those things in any future projects.


To be honest I don't see this as such a bad thing. Google Chrome has 70% of the browser market share, while Safari has 4%. I don't think there's anything wrong with prioritizing more popular platforms, specially when you just want to ship a project that you worked on in your spare time to learn new things.


Again, why I offered learning what was specific to Chrome and no longer using them for future projects. Yet more learning on top of the learning


What evidence is there that anything Chrome specific was used? Safari’s WebGL support has come later than others, and there are reports of WebGL being slower on Safari than Chrome, for example https://developer.apple.com/forums/thread/696821 It’s possible your incredulity maybe should be directed towards Safari and not someone trying to do their best?


Despite using firefox and wantind cross browser projects I think the learning involved in browser compatibility is a LOT less interesting then about the math behind animation.


If one cannot take valid criticism when posting publicly their pet projects, then don't post publicly.


You won’t find many people who consider this “valid” criticism. This is a pet project for educational purposes and you’re complaining because they’re not equivalently efficient on every platform.


`Meh. Just because "it's out of scope of what I planned" doesn't mean that with a few critiques/pointers along the way that it couldn't be better.

I understand the "let's do this for the lulz and see what happens/learns/etc", but once you feel like it is "good enough" that you post it to the public (for let's face it, publicity/showing off/self-promotion), you HAVE to expect that some people might think it isn't good enough and here's some ideas to make it better.

That's not to say that what was posted is shite. It's just with a bit more...it could be even more.


@dylan604 That sentence can be applied as well to your own opinion about wide browser compatibility.


That's a fair point. I'll leave it at that rather than trying to debate/belabor a day old thread.


This is exactly the type of project where recommending a specific browser is warranted.


Seeing glfw mentioned in your readme, I wanted to know how your (web) build process looks like. Gotta say I love this CMakeLists.txt It is so clean and simple!


I AM IN LOVE WITH THIS DATA:

But hear me out as to why:

Surely - the amount of spatial kinematic maths that has been built around how we 'perceive' natural movement within a scene by object has been immense...

---

I have an idea. (this is just off the cuff and what caused me to have goose-bumps immediately when I saw this):

Actually -- I am going to email you... rather than post publicly.

May you please update your profile with an email... or post a way to contact you here


I don't see any math, only visualization, where is the mathematical concepts and equations explained again?


Hi suyash, take a look at the README for information on what all the little graphs represent: https://github.com/diegomacario/Animation-Magic/blob/main/RE...

There's also a button in the controls that allows you to open the README. Thank you!


I agree.

For example I don't see a link between a given graph and one particular joint.

The README says each joint has (3 + 4 + 3) values but I only see graphs with 4 curves.

Ideas:

* allow to select a particular joint to only view the graphs related to that joint

* add titles to each graph

* allow to pause the animation, change the speed


Hi dolmen!

In the "Implementation Details" section at the bottom of the README I actually explain why I only display 4 curves instead of 10, and you can change the speed of the animation and pause it using the "Playback Speed" slider. If you set it to 0, the animation will pause.

Thanks for your suggestions about being able to select joints and displaying titles. I hope to improve things in the future!


I love this site, the animations have so much character!




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: