Paper.js is truly a great source of vector drawing tricks.
Curious how difficult it would be to extend this technique beyond two circles. Might have to dust off some old experiments ... :)
I'm extremely impressed with the implementation. I'm not sure what I would say if presented with a design like this slider for web. Wouldn't have imagined it would work this beautifully as well.
It definitely moved the opposite way I expected it to, but this way grew on me, hah.
It's not a perfect UI element - you can't actually see the options without scrolling through it all, but I could imagine something similar being a pretty cool little thing in the right context
Metaballs would not be for simulating fluids but for creating the simulated fluid's surface. In your youtube link it would be a step between "simulating particles" and "meshed result".
"Fluid simulation" was a bit of a nonsense response to that question, but there are similarities between metaballs and fluid simulations. The kernel functions used to interpolate Smoothed Particle Hydrodynamics samples are basically the same thing as metaball functions. The main difference is that you probably don't need the isosurface during simulation.
On a related note, one of the annoying things about metaballs for fluid surfacing is that there's some spooky action at a distance. Two drops of water will reach out towards each other as they come closer together, which makes no physical sense at all.
> SPH ... with 500 000 particles ... about 2.5 fps on my GTX 1070
Still slower than what CNCD & Fairlight demonstrated in 2011 with "Numb Res", at 120fps (stereo 3D) on a geforce 280:
> The demo features up to 500,000 particles running under 3D SPH in realtime on the GPU, with surface tension and viscosity terms; this is in combination with collisions, meshing, high end effects like MLAA and depth of field, and plenty of lighting effects
In order to render a surface you have to either use a contouring algorithm like marching cubes to generate a mesh like the above three.js demo, or raytrace or raymarch them. Because metaballs describe a distance function, its really easy to use SDF raymarching and there is a whole category dedicated to metaball shaders on shader toy (https://www.shadertoy.com/results?query=tag%3Dmetaballs).
It's possible to do this somewhat efficiently beyond two balls with GLSL and lots of uniforms (or a UBO), since metaballs from the graphics perspective are really just distance fields.
If you want more than a few balls, you can do it in two passes: one to produce the distance field, and one to threshold it.
As an added benefit, it's straightforward to generalize these approaches to any two-dimensional continuous function.
I did something fairly similar to this here: https://codepen.io/thomcc/pen/vLzyPY (I need to look into why this isn't running at 60fps anymore on my laptop, it certainly used to...)
The big difference is that it prerenders a gradient for each ball (it uses html5 canvas for that, but doing it with webgl is completely doable, although a bit more work), which is used as a distance field.
> I need to look into why this isn't running at 60fps anymore on my laptop, it certainly used to...
Runs at 60fps for me on a Chromebook from 2014. I suspect you're looking at it on macOS, which has had very poor (arguably the poorest of any x86 platform) OpenGL drivers for the last four or five years.
Far from the worst: if the update rate is reasonably low, this approach makes it a lot simpler to handle high-resolution displays, event registration. It should also run on a few more browsers and devices.
After years of living in the US, I still have trouble that the word is "cockpit" not "cocktip". That became hilariously obvious when at work we had to use a library that uses the term "cockpit" for one of its main components.
I would love to incorporate this in some of the UI design work we do for startups. Are there more similar libraries available? We could reference it to our network of clients (mostly developer driven startups) to help translate some of the design ideas we propose. If you know of other similar projects like Metaballs, please do share below or ping me (details in my bio)
I wonder how much would need to be adjusted to provide a scaling factor to the first metaball such that the area was constant (Thus ending up with two equally sized metaballs) or even utilizing the speed of the pull in determining the second balls size.
Metaballs are always nice, but I think this page (that was linked in the article) that shows compass&straight-edge constructions to be especially nifty:
Oh wow, it's a gaussian blur and basically a threshold function (boosting the contrast) using SVG filters! I didn't know this was possible. Very clever!
Feels more organic to me if the original metaball gets smaller as the other one moves out (like its stealing material). Haven't worked out the correct math but a quick PoC is here:
Keeping 100% accurate constant area would require a pretty insane closed form equation. Even ignoring the amount of area added by the stretched portions.
Yes, in this case a numeric approach would probably be the way to go:
- Assume that R1, R2 are the radii of the discs and A_ORIG is the original area (eg. R1^2 PI)
- Calculate the area A for a given R1, R2
- Multiply R1 and R2 with SQRT(A_ORIG / A)
- Repeat
If this doesn't converge after a few iterations, you can use the Newton method, or even a simple binary search to find he correct radii very quickly. A(k R1, k R2) should be monotonic for k, so solving it numerically for a given value should be trivial.
I just started learning GLSL shaders. As practice, I wrote a psuedo-metaball joystick. I didn't know about metaballs, but now that I do I can do some more research and improve my next iteration.
Much better. There's definitely many improvements that could be done, but that was the main one. The other big one is how the bigger disc doesn't change size.
The approximation OP does is a good start but still far from being real metaballs.
About 2 minutes in there's an excellent realtime metaballs implementation that ran smoothly on a 486-66mhz. Metaballs were an extremely popular effect in the early 90's.
Interesting approach! Coincidentally, I published an article [0] on this very topic last month. It uses sampling, so it's close to the approach mentioned in the Jamie Wong article you (and I) linked to, but with a path-tracing step capable of producing an SVG path definition. I'd be interested to see how the performance of these two methods stack up to each other for a given quality level.
During or just before WW2, Roy Liming developed analytic techniques for calculating a similar class of blend or fillet. They were taken up in aircraft design, a field that I can't imagine ever using implicit surfaces! I think it was Edgar Schmued's design for the P-51 Mustang that famously used Liming's work.
97 comments
[ 3.2 ms ] story [ 110 ms ] threadAmazing showcase.
It's not a perfect UI element - you can't actually see the options without scrolling through it all, but I could imagine something similar being a pretty cool little thing in the right context
Metaballs are way too expensive.
On a related note, one of the annoying things about metaballs for fluid surfacing is that there's some spooky action at a distance. Two drops of water will reach out towards each other as they come closer together, which makes no physical sense at all.
> SPH ... with 500 000 particles ... about 2.5 fps on my GTX 1070
Still slower than what CNCD & Fairlight demonstrated in 2011 with "Numb Res", at 120fps (stereo 3D) on a geforce 280:
> The demo features up to 500,000 particles running under 3D SPH in realtime on the GPU, with surface tension and viscosity terms; this is in combination with collisions, meshing, high end effects like MLAA and depth of field, and plenty of lighting effects
https://directtovideo.wordpress.com/2011/05/03/numb-res/
Works on Unix, Mac, iOS and Android
Code mirror is here - https://github.com/Zygo/xscreensaver
W.P. van Paassen's metaballs C code is here -
https://github.com/Zygo/xscreensaver/blob/master/hacks/metab...
Also, you can set various parameter tweaks for the metaballs from the command line or settings - count, radius etc.
https://threejs.org/examples/#webgl_marchingcubes
With the SVG/Bézier approach I doubt you could do 3D, true :)
In order to render a surface you have to either use a contouring algorithm like marching cubes to generate a mesh like the above three.js demo, or raytrace or raymarch them. Because metaballs describe a distance function, its really easy to use SDF raymarching and there is a whole category dedicated to metaball shaders on shader toy (https://www.shadertoy.com/results?query=tag%3Dmetaballs).
Interesting.
(Not affiliated with them, I just found https://blog.codepen.io/2017/10/05/regarding-referer-headers...)
It's possible to do this somewhat efficiently beyond two balls with GLSL and lots of uniforms (or a UBO), since metaballs from the graphics perspective are really just distance fields.
If you want more than a few balls, you can do it in two passes: one to produce the distance field, and one to threshold it.
As an added benefit, it's straightforward to generalize these approaches to any two-dimensional continuous function.
The big difference is that it prerenders a gradient for each ball (it uses html5 canvas for that, but doing it with webgl is completely doable, although a bit more work), which is used as a distance field.
Runs at 60fps for me on a Chromebook from 2014. I suspect you're looking at it on macOS, which has had very poor (arguably the poorest of any x86 platform) OpenGL drivers for the last four or five years.
https://codepen.io/keithclark/pen/sEbFz
I once reviewed an academic paper at a major CS conference that misspelled metaballs as meatballs throughout.
[1] https://www.youtube.com/watch?v=OonDPGwAyfQ
* https://www.gamasutra.com/view/feature/2438/how_to_prototype...
I had to struggle with metaball rendering on canvas back then. It was so slow. Now I guess a pixel shader in webGL can do a better job.
Check this out too: https://asadmemon.com/SPHjs/ source: https://github.com/asadm/SPHjs
I wonder how much would need to be adjusted to provide a scaling factor to the first metaball such that the area was constant (Thus ending up with two equally sized metaballs) or even utilizing the speed of the pull in determining the second balls size.
http://www.mathopenref.com/consttangentsext.html
Article for more detail: https://tympanus.net/codrops/2015/03/10/creative-gooey-effec...
https://codepen.io/femto113/pen/MEZava
- Assume that R1, R2 are the radii of the discs and A_ORIG is the original area (eg. R1^2 PI)
- Calculate the area A for a given R1, R2
- Multiply R1 and R2 with SQRT(A_ORIG / A)
- Repeat
If this doesn't converge after a few iterations, you can use the Newton method, or even a simple binary search to find he correct radii very quickly. A(k R1, k R2) should be monotonic for k, so solving it numerically for a given value should be trivial.
http://jamie-wong.com/2014/08/19/metaballs-and-marching-squa...
Touch blob joystick shader: https://www.shadertoy.com/view/4lfcRf
The approximation OP does is a good start but still far from being real metaballs.
About 2 minutes in there's an excellent realtime metaballs implementation that ran smoothly on a 486-66mhz. Metaballs were an extremely popular effect in the early 90's.
http://www.pouet.net/prod.php?which=1023
http://www.pouet.net/prod.php?which=911
How about first on the C64? Here's Booze in 2010:
http://www.pouet.net/prod.php?which=56003
[0] https://eightsquaredsoftware.com/articles/metaball.html
Beautiful article.
Liming wrote a book, but it's rare. Some technical discussion towards the end of this page: http://homepages.inf.ed.ac.uk/rbf/CVonline/LOCAL_COPIES/BOWY...