/* * Copyright (C) 2011 Michael Vogt <michu@neophob.com> * Copyright (C) 2012 Gyver * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.gyver.matrixmover.generator; import com.gyver.matrixmover.core.MatrixData; import com.gyver.matrixmover.generator.enums.GeneratorName; /** * The Class Metaballs. Calculates a classic metaballs effect. * * Code-parts copied from http://github.com/neophob/PixelController * * @author Gyver * */ public class MetaBalls extends Generator { /** The blob px. */ private float[] blobPx; /** The blob py. */ private float[] blobPy; /** The blob dx. */ private float[] blobDx; /** The blob dy. */ private float[] blobDy; /** The vx. */ private int[][] vy, vx; /** The a. */ private int a = 1; private int numBlobs; private int size; private float speed; private int threshold; private boolean applyThreshold; /** * Instantiates a new metaballs. * * @param md the MatrixData of the Matrix */ public MetaBalls(MatrixData md) { super(GeneratorName.METABALLS, md); this.numBlobs = 2; this.size = 1000; this.speed = 0.1F; this.applyThreshold = false; this.threshold = 128; blobPx = new float[numBlobs]; blobPy = new float[numBlobs]; blobDx = new float[numBlobs]; blobDy = new float[numBlobs]; for (int i = 0; i < numBlobs; i++){ blobPx[i] = (int) Math.floor(Math.random()*internalBufferWidth); blobPy[i] = (int) Math.floor(Math.random()*internalBufferHeight); blobDx[i] = (float) ((Math.random()-0.5)*2); blobDy[i] = (float) ((Math.random()-0.5)*2); } vy = new int[numBlobs][getInternalBufferYSize()]; vx = new int[numBlobs][getInternalBufferXSize()]; } @Override public void init(){ blobPx = new float[numBlobs]; blobPy = new float[numBlobs]; blobDx = new float[numBlobs]; blobDy = new float[numBlobs]; for (int i = 0; i < numBlobs; i++){ blobPx[i] = (int) Math.floor(Math.random()*internalBufferWidth); blobPy[i] = (int) Math.floor(Math.random()*internalBufferHeight); blobDx[i] = (float) ((Math.random()-0.5)*2); blobDy[i] = (float) ((Math.random()-0.5)*2); } vy = new int[getNumBlobs()][internalBufferHeight]; vx = new int[getNumBlobs()][internalBufferWidth]; } @Override public void update() { float f; for (int i = 0; i < numBlobs; ++i) { f = (float) Math.sin((i + 1) * 3 + 5 * blobPx[i]); f *= 3f; if (f < 0) { f = 0 - f; } f += 0.5f; blobPx[i] += blobDx[i] * f * speed; f = (float) Math.cos(a % 256 + (i + 3) * blobPy[i]); f *= 3f; if (f < 0) { f = 0 - f; } f += 0.5f; blobPy[i] += blobDy[i] * f * speed; // bounce across screen if (blobPx[i] < 0 && blobDx[i] < 0) { blobDx[i] *= -1; } if (blobPx[i] > internalBufferWidth && blobDx[i] > 0) { blobDx[i] *= -1; } if (blobPy[i] < 0 && blobDy[i] < 0) { blobDy[i] *= -1; } if (blobPy[i] > internalBufferHeight && blobDy[i] > 0) { blobDy[i] *= -1; } for (int x = 0; x < internalBufferWidth; x++) { vx[i][x] = (int) Math.floor((blobPx[i] - x) * (blobPx[i] - x)); } for (int y = 0; y < internalBufferHeight; y++) { vy[i][y] = (int) Math.floor((blobPy[i] - y) * (blobPy[i] - y)); } } a++; if (a > 0xffff) { a = 1; } for (int y = 0; y < internalBufferHeight; y++) { for (int x = 0; x < internalBufferWidth; x++) { int m = 1; for (int i = 0; i < numBlobs; i++) { // Increase this number to make your blobs bigger m += getSize() / (vy[i][y] + vx[i][x] + 1); } int intensity = (x+m+y)/3; if (intensity > 255) { intensity = 255; } if(isApplyThreshold()){ if(intensity > threshold){ intensity = 255; } else { intensity = 0; } } this.internalBuffer[y * internalBufferWidth + x] = (intensity << 16) | (intensity << 8) | (intensity); } } } /** * Returns the number of blobs * @return the numBlobs */ public int getNumBlobs() { return numBlobs; } /** * Sets the number of blobs * @param numBlobs the numBlobs to set */ public void setNumBlobs(int numBlobs) { this.numBlobs = numBlobs; init(); } /** * Returns the size of the blobs * @return the size */ public int getSize() { return size; } /** * Sets the size of the blobs * @param size the size to set */ public void setSize(int size) { this.size = size; } /** * Returns the speed of the blobs * @return the speed */ public int getSpeed() { return (int) Math.round(speed*100); } /** * Sets the speed of the blobs * @param speed the speed to set */ public void setSpeed(float speed) { this.speed = speed/100; } /** * Returns the threshold * @return the threshold */ public int getThreshold() { return threshold; } /** * Sets the threshold * @param threshold the threshold to set */ public void setThreshold(int threshold) { this.threshold = threshold; } /** * Returns, if threshold is applied * @return the applyThreshold */ public boolean isApplyThreshold() { return applyThreshold; } /** * Sets to apply the threshold or not * @param applyThreshold the applyThreshold to set */ public void setApplyThreshold(boolean applyThreshold) { this.applyThreshold = applyThreshold; } }