I’ve updated my Mockup Generator
For my students at Elisava, I have updated my mockup generator. Now its possible to load animations in the .gif format, instead of inporting a whole folder of single frames in png format, which makes the whole process much smoother.
To use it, you need to install two libraries: GifAnimation and VideoExport. Please note: Unfortunately I can’t give any support for this application, but I am very thankful for feedback.
If you need help, please post your question on the Discord server.
Related
// #####################################
// The trcc mockup generator - 2023 edition
// Controls:
// 1-4 - edit points
// r - record video
// g - show/hide grid
// p - change position
// o - skew
// #####################################
// Settings for the project
int WIDTH = 1920;
int HEIGHT = 1080;
String SCENE_IMAGE_FILENAME = "20.jpg";
String INPUT = "input/input.gif_50x10.gif";
float SCALE_FROM = 1; // Ken Burns Zoom
float SCALE_TO = 1.2;
// #####################################
// Application State
PImage sceneImage;
PGraphics pg;
PGraphics grid;
boolean record = false;
boolean showGrid = true;
boolean showUi = true;
boolean VectorSelectionMode = false;
// Positions of the 4 Vectors
float initialMagX = 300;
float initialMagY = 200;
float v1x = -initialMagX;
float v1y = -initialMagY;
float v2x = initialMagX;
float v2y = -initialMagY;
float v3x = initialMagX;
float v3y = initialMagY;
float v4x = -initialMagX;
float v4y = initialMagY;
int DESIGN = 0;
int SELECTIMAGE = 1;
int view = DESIGN;
import gifAnimation.*;
PImage[] animation;
void setup() {
sceneImage = loadImage("scenes/" + SCENE_IMAGE_FILENAME);
sceneImage.filter(GRAY);
pg = createGraphics(WIDTH, HEIGHT, P3D);
frameRate(30);
animation = Gif.getPImages(this, INPUT);
}
void settings() {
size(WIDTH / 2, HEIGHT / 2, P3D);
pixelDensity(2);
}
float offsetX = 0;
float offsetY = 0;
float W = 1;
float H = 1;
float scalarValue = 1;
void draw() {
background(0);
if (record) {
playSequence();
}
pg.beginDraw();
pg.clear();
pg.imageMode(CENTER);
pg.push();
pg.translate(width/2, height/2);
// Ken Burns Zoom
if (record) {
float kenBurnsScalar = map(recordFrame, 1, animation.length, SCALE_FROM, SCALE_TO);
pg.scale(kenBurnsScalar);
}
// /END Ken Burns Zoom
pg.push();
pg.translate(offsetX, offsetY);
//pg.scale(scalarValue);
pg.scale(W, H);
if (record) {
pg.noTint();
} else {
pg.tint(255, 170);
}
pg.image(sceneImage, 0, 0);
pg.pop();
if (vectorSelector == 1) {
v1x = -width/2+mouseX;
v1y = -height/2+mouseY;
}
if (vectorSelector == 2) {
v2x = -width/2+mouseX;
v2y = -height/2+mouseY;
}
if (vectorSelector == 3) {
v3x = -width/2+mouseX;
v3y = -height/2+mouseY;
}
if (vectorSelector == 4) {
v4x = -width/2+mouseX;
v4y = -height/2+mouseY;
}
pg.imageMode(CENTER);
pg.push();
pg.translate(0, 0);
pg.textureMode(NORMAL);
pg.textureWrap(CLAMP);
pg.noFill();
if (!record) {
pg.strokeWeight(3);
pg.stroke(#00ff00);
} else {
pg.noStroke();
}
//pg.stroke(#00FF00);
if (record) {
PImage textureImage = animation[recordFrame];
float tilesX = 8;
float tilesY = 8;
PVector d1 = new PVector(v1x, v1y);
PVector d2 = new PVector(v2x, v2y);
PVector d3 = new PVector(v3x, v3y);
PVector d4 = new PVector(v4x, v4y);
int res = 10;
float yres = 1.0/(res-1);
float xres = 1.0/(res-1);
// Precalc grid positions
PVector[][] grid = new PVector[res][res];
for (int y=0; y<res; y++) {
for (int x=0; x<res; x++) {
grid[x][y] = new PVector(
lerp(
lerp(d1.x, d2.x, x*xres),
lerp(d4.x, d3.x, x*xres),
y*yres),
lerp(
lerp(d1.y, d4.y, y*yres),
lerp(d2.y, d3.y, y*yres),
x*xres)
);
}
}
for (int y=0; y<res-1; y++) {
for (int x=0; x<res-1; x++) {
pg.beginShape();
pg.texture(textureImage);
pg.vertex(grid[x][y].x, grid[x][y].y, x*xres, y*yres);
pg.vertex(grid[x+1][y].x, grid[x+1][y].y, (x+1)*xres, y*yres);
pg.vertex(grid[x+1][y+1].x, grid[x+1][y+1].y, (x+1)*xres, (y+1)*yres);
pg.vertex(grid[x][y+1].x, grid[x][y+1].y, x*xres, (y+1)*yres);
pg.endShape();
}
}
pg.endDraw();
} else {
pg.beginShape();
pg.vertex(v1x, v1y, 0, 0);
pg.vertex(v2x, v2y, 1, 0);
pg.vertex(v3x, v3y, 1, 1);
pg.vertex(v4x, v4y, 0, 1);
pg.endShape(CLOSE);
}
pg.pop();
pg.pop();
pg.endDraw();
image(pg, 0, 0);
if (!record) {
image(displayGrid(), 0, 0);
// Show UI only when vectorSelection is Off!
if (!VectorSelectionMode) {
//cp5.draw();
}
}
recordVideo();
rec(30,10000);
editMockup();
// rec(30,10000);
}
// #####################################
// Edit Modes
int EDIT_POSITION = 1;
int EDIT_SKEW = 2;
void editMockup() {
if (editMode == EDIT_POSITION) {
offsetX = map(mouseX, 0, width, -1000, 1000);
offsetY = map(mouseY, 0, height, -1000, 1000);
} else if (editMode == EDIT_SKEW) {
W = map(mouseX, 0, width, 0.2, 2);
H = map(mouseY, 0, height, 0.2, 2);
scalarValue = 1;
}
}
PGraphics displayGrid(){
PGraphics pg = createGraphics(WIDTH,HEIGHT);
pg.beginDraw();
pg.clear();
pg.rectMode(CENTER);
pg.fill(#ff00ff);
pg.noStroke();
float gridThickness = 1;
pg.rect(width/2,height/2,gridThickness,height);
pg.rect(width/4,height/2,gridThickness,height);
pg.rect(width/4*3,height/2,gridThickness,height);
pg.rect(width/2,height/2,width,gridThickness);
pg.endDraw();
return pg;
}
final String sketchname = getClass().getName();
import com.hamoid.*;
VideoExport videoExport;
void rec(int rate, int dur) {
if (frameCount == 1) {
videoExport = new VideoExport(this, "../"+sketchname+".mp4");
videoExport.setFrameRate(rate);
videoExport.startMovie();
}
videoExport.saveFrame();
if (frameCount == dur) {
exit();
}
println(frameCount);
}
int recordFrame = 1;
int recordFrameRate = 5;
float sceneScalar = 0;
void launchRecordVideo() {
record = !record;
recordFrame = 1;
}
void playSequence() {
if (recordFrame < animation.length-1) {
recordFrame++;
} else {
recordFrame = 0;
sceneScalar += 0.01;
exit();
println("finished recording");
}
}
void recordVideo() {
// saveFrame("out/" + INPUT + nf(recordFrame, 4) + ".jpg");
}
int vectorSelector = 0;
int editMode = 0;
void keyReleased() {
if (key == '1') {
vectorSelector = 1;
VectorSelectionMode = true;
editMode = 0;
} else if (key == '2') {
vectorSelector = 2;
VectorSelectionMode = true;
editMode = 0;
} else if (key == '3') {
vectorSelector = 3;
VectorSelectionMode = true;
editMode = 0;
} else if (key == '4') {
vectorSelector = 4;
VectorSelectionMode = true;
editMode = 0;
} else {
vectorSelector = 0;
VectorSelectionMode = false;
editMode = 0;
}
if (key == 'r') {
editMode = 0;
launchRecordVideo();
}
if (key == 'g') {
editMode = 0;
showGrid = !showGrid;
}
if (key == 'p') {
editMode = EDIT_POSITION;
}
if (key == 'o') {
editMode = EDIT_SKEW;
}
}
void mouseReleased() {
vectorSelector = 0;
VectorSelectionMode = false;
}
Related

Once again, I had the honor of illustrating an article for the New York Times that I myself am very […]

A few months ago I made a small app that allows you to create image collages with some kind of […]

Since the beginning of the Corona crisis, I have been more and more interested in the history of ancient philosophy. […]

Together with Lena Weber I created the promo video for Slate + Ash’s brand new software synth called Choreographs. The […]

Some of you may know that I have a split relationship with Instagram. Still, even though I often find myself […]

Generative visuals made from the "Prelude in C" by Johann Sebastian Bach.