Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
/*
Metaballs proof of concept by Stefan Petrick
...very rough 8bit math here...
read more about the concept of isosurfaces and metaballs:
https://www.gamedev.net/articles/programming/graphics/exploring-metaballs-and-isosurfaces-in-2d-r2556
*/
#include "FastLED.h"
uint8_t Width = 16;
uint8_t Height = 16;
#define NUM_LEDS 256
#define BRIGHTNESS 127
CRGB leds[NUM_LEDS];
void setup() {
Serial.begin(115200);
// Adjust this for you own setup. Use the hardware SPI pins if possible.
// On Teensy 3.1/3.2 the pins are 11 & 13
// Details here: https://github.com/FastLED/FastLED/wiki/SPI-Hardware-or-Bit-banging
// In case you see flickering / glitching leds, reduce the data rate to 12 MHZ or less
LEDS.addLeds<APA102, 11, 13, BGR, DATA_RATE_MHZ(12)>(leds, NUM_LEDS);
FastLED.setBrightness(BRIGHTNESS);
FastLED.setDither(DISABLE_DITHER);
}
void loop() {
MetaBalls();
//show_fps();
}
// check the Serial Monitor for fps rate
void show_fps() {
EVERY_N_MILLIS(100) {
Serial.println(LEDS.getFPS());
}
}
void CLS() {
for (uint16_t i = 0; i < NUM_LEDS; i++) {
leds[i] = 0x000000;
}
}
// this finds the right index within a serpentine matrix
uint16_t XY( uint8_t x, uint8_t y) {
uint16_t i;
if ( y & 0x01) {
uint8_t reverseX = (Width - 1) - x;
i = (y * Width) + reverseX;
} else {
i = (y * Width) + x;
}
return i;
}
void MetaBalls() {
float speed = 1;
// get some 2 random moving points
uint8_t x2 = inoise8(millis() * speed, 25355, 685 ) / 16;
uint8_t y2 = inoise8(millis() * speed, 355, 11685 ) / 16;
uint8_t x3 = inoise8(millis() * speed, 55355, 6685 ) / 16;
uint8_t y3 = inoise8(millis() * speed, 25355, 22685 ) / 16;
// and one Lissajou function
uint8_t x1 = beatsin8(23 * speed, 0, 15);
uint8_t y1 = beatsin8(28 * speed, 0, 15);
for (uint8_t y = 0; y < Height; y++) {
for (uint8_t x = 0; x < Width; x++) {
// calculate distances of the 3 points from actual pixel
// and add them together with weightening
uint8_t dx = abs(x - x1);
uint8_t dy = abs(y - y1);
uint8_t dist = 2 * sqrt((dx * dx) + (dy * dy));
dx = abs(x - x2);
dy = abs(y - y2);
dist += sqrt((dx * dx) + (dy * dy));
dx = abs(x - x3);
dy = abs(y - y3);
dist += sqrt((dx * dx) + (dy * dy));
// inverse result
byte color = 1000 / dist;
// map color between thresholds
if (color > 0 and color < 60) {
leds[XY(x, y)] = CHSV(color * 9, 255, 255);
} else {
leds[XY(x, y)] = CHSV(0, 255, 255);
}
// show the 3 points, too
leds[XY(x1,y1)] = CRGB(255, 255,255);
leds[XY(x2,y2)] = CRGB(255, 255,255);
leds[XY(x3,y3)] = CRGB(255, 255,255);
}
}
FastLED.show();
//CLS();
}
@DedeHai

This comment has been minimized.

Copy link

@DedeHai DedeHai commented Nov 4, 2018

interesting stuff. I am currently looking for new animations for my LED matrix (noise & plasma stuff) and stumbled upon your code. I did a similar thing but using particles a few years ago, unfortunately I do not have any video of it but here is a demo of a matrix showing a few animations, first one is a simplyfied heat transfer finite elements simulation. https://www.youtube.com/watch?v=F7fd7MILKFU
Any chance you have a video of what the metaballs animation looks like?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.