abstract class AnimationTemplate
{
protected final PApplet processing;
protected String imageName;
protected float explosionUpperBound;
protected float explosionLowerBound;
protected float explosionStep;
protected float explosionCurrentPosition;
protected int fillColorAlpha;
protected int movieType = MovieMaker.MOTION_JPEG_A;
final static int framePerSecond = 30;
final static int numberOfFramesForEndPadding = 45;
protected PImage image;
private boolean writeVideo;
protected MovieMaker movieBuilder;
AnimationTemplate(PApplet processing, String imageName, boolean writeVideo) {
this.processing = processing;
this.imageName = imageName;
image = processing.loadImage(this.imageName);
this.writeVideo = writeVideo;
if (writeVideo == true)
{
movieBuilder = new MovieMaker(this.processing, getScreenWidth(), getScreenHeight(), "video.mov",
framePerSecond, movieType, MovieMaker.HIGH);
}
}
public PImage loadImage() {
return image;
}
public int getFillColorAlphaValue() {
return fillColorAlpha;
}
public float getNextExplosionPosition() {
float result = explosionCurrentPosition;
if (explosionCurrentPosition > explosionLowerBound)
{
explosionCurrentPosition += explosionStep;
}
else if (movieBuilder != null)
{
explosionCurrentPosition = 0f;
}
println(result);
return result;
}
public void addVideoFrame() {
if (movieBuilder == null)
{
return;
}
if (explosionCurrentPosition > explosionLowerBound)
{
movieBuilder.addFrame();
}
else
{
for (int i = numberOfFramesForEndPadding; i > 0; --i)
{
movieBuilder.addFrame();
}
movieBuilder.finish();
exit();
}
}
protected void setExplosionStep(float explosionStep)
{
this.explosionStep = explosionStep;
if (writeVideo == false)
{
this.explosionStep = this.explosionStep * 40f;
}
}
public abstract int getScreenWidth();
public abstract int getScreenHeight();
public abstract boolean getUseShortDistanceRendering();
public abstract float getTranslatePositionX(float x);
public abstract float getTranslatePositionY(float y);
}
import processing.video.*;
PImage sourceImage;
int cellsize = 1;
int columnsNumber, rowsNumber;
float explosionPosition;
//int[] xRotationDirection = {0, 1, 1, 0, -1, -1, -1, 0};
//int[] yRotationDirection = {1, 1, 0, -1, -1, -1, 0, 1};
int[] yRotationDirection = {1, -1, 1, 1, 1, -1, 1, 1};
int xyRotationDirectionIndex = 0;
AnimationTemplate animationInfo;
void setup() {
size(500, 333, P3D);
boolean generateVideoFile = false;
animationInfo = new ShakingForest(this, generateVideoFile);
if (animationInfo.getScreenWidth() != width || animationInfo.getScreenHeight() != height)
{
//error message: instructions with the right arguments for the size() call
println("Set video size to " + animationInfo.getScreenWidth() + ", " + animationInfo.getScreenHeight() + " in the setup()");
exit();
}
sourceImage = animationInfo.loadImage();
columnsNumber = sourceImage.width / cellsize;
rowsNumber = sourceImage.height / cellsize;
}
void draw() {
background(0);
explosionPosition = animationInfo.getNextExplosionPosition();
for ( int columnI = 0; columnI < columnsNumber; columnI++) {
for ( int rowJ = 0; rowJ < rowsNumber; rowJ++) {
int xPosition = columnI * cellsize;
int yPosition = rowJ * cellsize;
int pixelArrayLocation = xPosition + yPosition*sourceImage.width;
color pixelColor = sourceImage.pixels[pixelArrayLocation];
float zPosition = (explosionPosition * 50 / float(width)) * brightness(sourceImage.pixels[pixelArrayLocation]) / 10 - 20.0;
drawPixelExplodedIn3Dspace(xPosition, yPosition, zPosition, pixelColor);
}
}
animationInfo.addVideoFrame();
}
void drawPixelExplodedIn3Dspace(float xPosition, float yPosition, float zPosition, color pixelColor) {
pushMatrix();
translate(animationInfo.getTranslatePositionX(xPosition), animationInfo.getTranslatePositionY(yPosition), zPosition);
fill(pixelColor, animationInfo.getFillColorAlphaValue());
noStroke();
if (animationInfo.getUseShortDistanceRendering() == false)
{
//rotateX((abs(zPosition + 20.0) % TWO_PI) * xRotationDirection[xyRotationDirectionIndex]);
rotateY((abs(zPosition + 20.0) % TWO_PI) * yRotationDirection[xyRotationDirectionIndex]);
xyRotationDirectionIndex = (xyRotationDirectionIndex + 1) % 8;
ellipseMode(CENTER);
ellipse(0, 0, cellsize * 4, cellsize * 4);
}
else
{
rectMode(CENTER);
rect(0, 0, cellsize * 4, cellsize * 4);
}
popMatrix();
}
class ShakingForest extends AnimationTemplate {
ShakingForest(PApplet processing) {
this(processing, false);
}
ShakingForest(PApplet processing, boolean writeVideo) {
super(processing, "moaan_3065890530_091c5c3d88.jpg", writeVideo);
explosionUpperBound = 120f;
explosionLowerBound = 10f;
explosionCurrentPosition = explosionUpperBound;
this.setExplosionStep(-0.25f);
fillColorAlpha = 255;
}
public int getScreenWidth() {
return image.width;
}
public int getScreenHeight() {
return image.height;
}
public boolean getUseShortDistanceRendering() {
return false;
}
public float getTranslatePositionX(float x) {
return x;
}
public float getTranslatePositionY(float y) {
return y;
}
}
class Test extends AnimationTemplate {
Test(PApplet processing) {
this(processing, false);
}
Test(PApplet processing, boolean writeVideo) {
super(processing, "autunno_al_lago_2.JPG", writeVideo);
explosionUpperBound = 170f;
explosionLowerBound = 0f;
explosionCurrentPosition = explosionUpperBound;
this.setExplosionStep(-0.25f);
fillColorAlpha = 255;
}
public int getScreenWidth() {
return image.width;
}
public int getScreenHeight() {
return image.height;
}
public boolean getUseShortDistanceRendering() {
return false;
}
public float getTranslatePositionX(float x) {
return x;
}
public float getTranslatePositionY(float y) {
return y;
}
}