Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <public_stuff.hpp>
- #include <math.h>
- #define METABALL_THRESHHOLD 75.0f
- #define METABALL_SPEED 500.0f
- #define METABALL_COUNT 400
- struct Metaball {
- f32 x, y, m;
- f32 velX, velY;
- };
- static Metaball metaballs[METABALL_COUNT];
- static void reset_metaballs(){
- #define MBCOUNT_FRACT(x,y) ((f32)METABALL_COUNT*((f32)(x)/(y)))
- for(int i=0; i<METABALL_COUNT; ++i){
- metaballs[i].x = frandf()*CANVAS_W;
- metaballs[i].y = frandf()*CANVAS_H;
- metaballs[i].m = frandf()*MBCOUNT_FRACT(3.0f,4) + MBCOUNT_FRACT(1.0f,4);
- metaballs[i].velX = frandf2()*METABALL_SPEED;
- metaballs[i].velY = frandf2()*METABALL_SPEED;
- }
- }
- static inline f32 distancef(f32 x0, f32 y0,
- f32 x1, f32 y1, f32 m)
- {
- x0 -= x1;
- y0 -= y1;
- const f32 result = sqrtf(x0*x0+y0*y0);
- return m / (result*result);
- }
- static inline Color8 sum_metaballs(f32 x, f32 y){
- // Note: convert to f64 if too many rounding errors start happening
- f32 sum = 0.0f;
- for(int i=0; i<METABALL_COUNT; ++i)
- sum += distancef(x, y, metaballs[i].x, metaballs[i].y, metaballs[i].m);
- // Monochromatic
- //return 255 * (sum < METABALL_THRESHHOLD);
- // Balls of light
- //#define GRAY(u) MIN(16*(s32)( (u)*16.0f + 0.5f ), 255)
- //return GRAY(MIN(sum/METABALL_THRESHHOLD, 1.0f));
- // Black-and-white trippy look
- //#define GRAY(u) (16*(s32)( (u)*16.0f + 0.5f ))
- //return GRAY(sum/METABALL_THRESHHOLD);
- // Normal trippy look
- return 255 * (sum/METABALL_THRESHHOLD);
- }
- static void render_metaballs(){
- for(PixelCoords i=0; i.v<(CANVAS_W*CANVAS_H); ++i.v)
- //pixels[i.v] = sum_metaballs((f32)i.x, (f32)i.y);
- pixels[i.v] = sum_metaballs((f32)(i.v&255), (f32)(i.v>>8));
- }
- static void animate_metaballs(){
- #define OPTIMAL_FRAME (1000.0/62.5) // 16ms
- #define COEFFICIENT_DIV (1.0/OPTIMAL_FRAME)
- #define LASTTIME_START 0xFFFFFFFFFFFFFFFF // = 2^64 - 1
- static u64 timeLast = LASTTIME_START;
- const u64 timeThis = timeGetPerfCounter();
- if(timeLast == LASTTIME_START) timeLast = timeThis;
- // Note: convert to f64 if too many rounding errors start happening
- const f32 timeDelta = (f32)(timeThis-timeLast)/timeGetPerfFreq();
- timeLast = timeThis;
- for(int i=0; i<METABALL_COUNT; ++i){
- // Note: convert to f64 if too many rounding errors start happening
- const f32 coefficient = timeDelta*COEFFICIENT_DIV;
- Metaball& metaball = metaballs[i];
- metaball.x += metaball.velX*coefficient;
- metaball.y += metaball.velY*coefficient;
- if(metaball.x<0 || metaball.x>=CANVAS_W){
- metaball.velX = -metaball.velX;
- metaball.x = CLAMP(metaball.x, 0, CANVAS_W-1);
- }
- if(metaball.y<0 || metaball.y>=CANVAS_H){
- metaball.velY = -metaball.velY;
- metaball.y = CLAMP(metaball.y, 0, CANVAS_H-1);
- }
- }
- }
- int user_main(int argc, char** argv){
- #define GAMMA 0.45
- for(int i=0; i<256; ++i){
- u8 gray = u8( 255 * pow((f64)i/255, 1.0/(GAMMA)) );
- Color24 color(gray, gray, gray);
- update_palette(&color, i, 1);
- }
- //_lbl_start:
- reset_metaballs();
- while(!win_closed){
- //Handle events
- Event evt;
- while(pollEvent(&evt))
- switch(evt.type){
- case EVENT_QUIT: return 0; // No break needed
- //case EVENT_KEY_DOWN: goto _lbl_start;
- default:;
- }
- // Draw stuff
- u64 timeStart = timeGetPerfCounter();
- // (No need to call canvas_clear(); this overwrites all pixels anyway!)
- render_metaballs();
- canvas_present(true);
- animate_metaballs();
- u64 timeEnd = timeGetPerfCounter();
- f64 timeDelta = (f64)(timeEnd-timeStart)/timeGetPerfFreq();
- // Waits for about 16ms to approximate 60fps
- timeDelta = (0.016-timeDelta);
- timeSleep( (u32)MAX(1, (s32)(1000.0*timeDelta + 0.5)) );
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement