Processing making a draw method slowly? - processing

I am working on Processing language and have a code like that:
int fatness=30;
int step=20;
void drawCircle() {
fill(48, 139, 206);
ellipse(width - fatness, height - fatness, fatness, fatness);
}
void increaseCircle(){
fatness = fatness + step;
}
at another class I want to call the increaseCircle() method. However I want it getting bigger slowly. I mean step makes it 20 more bigger at my code but I want it make bigger i.e. at 2 seconds if possible with an animation. How can I do that?
EDIT: When I define an object from that class and call increaseCircle method it gets bigger and bigger, doesn't stop?

Sounds like you need to update the values based on time.
If you store the start time, you can always check how much time passed using the millis() function.
Once you know how much time passed, you can divide that difference to the duration you want for updating your variable(fatness in you case).
This will give you value between 0.0 and 1.0, which you can use to scale/multiply to the final desired value for your variable (e.g. fatness goes from 20 to 200).
Here's what I mean:
int startTime;
int duration = 1000;
float startValue = 20;
float endValue = 200;
float currentValue = startValue;
void setup(){
size(400,400,P2D);
ellipseMode(CENTER);
startTime = millis();
}
void draw(){
background(255);
increaseCircle();
drawCircle();
}
void drawCircle() {
fill(48, 139, 206);
ellipse(width - currentValue, height - currentValue, currentValue, currentValue);
}
void increaseCircle(){
float progress = (float)(millis()-startTime)/duration;//millis()-startTime = difference in time from start until now
if(progress <= 1.0) currentValue = startValue + (endValue * progress);//the current value is the final value scaled/multiplied by the ratio between the current duration of the update and the total duration
}
void mousePressed(){//reset value and time
currentValue = startValue;
startTime = millis();
}
void keyPressed(){//update duration
if(key == '-') if(duration > 0) duration -= 100;
if(key == '=' || key == '+') duration += 100;
println("duration: " + duration);
}
In this simple demo you can click to reset the animation and use the - and = keys to increase or decrease the animation duration.
If you're comfortable with using external libraries in Processing, you should have a look at this library.
You can run a demo bellow:
var startTime;
var duration = 1000;
var startValue = 20;
var endValue = 200;
var currentValue = startValue;
function setup(){
createCanvas(400,400);
ellipseMode(CENTER);
startTime = millis();
}
function draw(){
background(255);
increaseCircle();
drawCircle();
}
function drawCircle() {
fill(48, 139, 206);
ellipse(width - currentValue, height - currentValue, currentValue, currentValue);
}
function increaseCircle(){
var progress = (float)(millis()-startTime)/duration;//millis()-startTime = difference in time from start until now
if(progress <= 1.0) currentValue = startValue + (endValue * progress);//the current value is the final value scaled/multiplied by the ratio between the current duration of the update and the total duration
}
function mousePressed(){//reset value and time
currentValue = startValue;
startTime = millis();
}
function keyPressed(){//update duration
if(key == '-') if(duration > 0) duration -= 100;
if(key == '=' || key == '+') duration += 100;
println("duration: " + duration);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.4.4/p5.min.js"></script>

Related

Automation of selection in Processing

I am currently using a processing sketch to work through a large number of images I have in a folder. I have set an onClick command to advance to the next image in the string. It is quite time consuming and I would like to automate the action that once the sketch is completed the sketch would repeat it's self selecting the next image from the string. The onClick command also save the image the export folder but each time saves with the same file name, I've tried to set up sequential numbering but it hasn't worked so far. Any help would be greatly appreciated.
String[] imgNames = {"1.jpg", "2.jpg", "3.jpg"};
PImage img;
int imgIndex = 0;
void nextImage() {
background(255);
frameRate(10000);
loop();
frameCount = 0;
img = loadImage(imgNames[imgIndex]);
img.loadPixels();
imgIndex += 1;
if (imgIndex >= imgNames.length) {
imgIndex = 0;
}
}
void paintStroke(float strokeLength, color strokeColor, int strokeThickness) {
float stepLength = strokeLength/4.0;
// Determines if the stroke is curved. A straight line is 0.
float tangent1 = 0;
float tangent2 = 0;
float odds = random(1.0);
if (odds < 0.7) {
tangent1 = random(-strokeLength, strokeLength);
tangent2 = random(-strokeLength, strokeLength);
}
// Draw a big stroke
noFill();
stroke(strokeColor);
strokeWeight(strokeThickness);
curve(tangent1, -stepLength*2, 0, -stepLength, 0, stepLength, tangent2, stepLength*2);
int z = 1;
// Draw stroke's details
for (int num = strokeThickness; num > 0; num --) {
float offset = random(-50, 25);
color newColor = color(red(strokeColor)+offset, green(strokeColor)+offset, blue(strokeColor)+offset, random(100, 255));
stroke(newColor);
strokeWeight((int)random(0, 3));
curve(tangent1, -stepLength*2, z-strokeThickness/2, -stepLength*random(0.9, 1.1), z-strokeThickness/2, stepLength*random(0.9, 1.1), tangent2, stepLength*2);
z += 1;
}
}
void setup() {
size(1600, 700);
nextImage();
}
void draw() {
translate(width/2, height/2);
int index = 0;
for (int y = 0; y < img.height; y+=1) {
for (int x = 0; x < img.width; x+=1) {
int odds = (int)random(20000);
if (odds < 1) {
color pixelColor = img.pixels[index];
pixelColor = color(red(pixelColor), green(pixelColor), blue(pixelColor), 100);
pushMatrix();
translate(x-img.width/2, y-img.height/2);
rotate(radians(random(-90, 90)));
// Paint by layers from rough strokes to finer details
if (frameCount < 20) {
// Big rough strokes
paintStroke(random(150, 250), pixelColor, (int)random(20, 40));
} else if (frameCount < 1000) {
// Thick strokes
paintStroke(random(75, 125), pixelColor, (int)random(8, 12));
} else if (frameCount < 1500) {
// Small strokes
paintStroke(random(20, 30), pixelColor, (int)random(1, 4));
} else if (frameCount < 10000) {
// Big dots
paintStroke(random(5, 10), pixelColor, (int)random(5, 8));
} else if (frameCount < 10000) {
// Small dots
paintStroke(random(1, 2), pixelColor, (int)random(1, 3));
}
popMatrix();
}
index += 1;
}
}
if (frameCount > 10000) {
noLoop();
}
// if(key == 's'){
// println("Saving...");
// saveFrame("screen-####.jpg");
// println("Done saving.");
// }
}
void mousePressed() {
save("001.tif");
nextImage();
}
Can't you just call the nextImage() function from inside this if statement?
if (frameCount > 10000) {
noLoop();
}
Would be:
if (frameCount > 10000) {
nextImage();
}
As for using different filenames, just use an int that you increment whenever you save the file, and use that value in the save() function. Or you could use the frameCount variable:
save("img" + frameCount + ".tif");
If you have follow-up questions, please post a MCVE instead of your whole project. Try to isolate one problem at a time in a small example program that only does that one thing. Good luck.

Array index out of bounds exception: 100

//----------------------------------------------\\
float x = 300;
float y = 300;
float direction = 0;
float increment = 1;
float speed = 5;
boolean toggle = true; // - For spaceship reversal
float wormX = random(0, 600); // - For wormHole v
float wormY = random(0, 600);
float wormGrowth = 0;
boolean growthSwitch = true; // - for wormHole ^
float[] starXpos = new float[100]; //starsRandom
float[] starYpos = new float[100]; //starsRandom
float d = dist(x, y, wormX, wormY);
int score = 0;
//----------------------------------------------\\
//----------------------------------------------\\ Setup
void setup (){
size (600, 600);
starsP1();
}
//----------------------------------------------\\ Draw
void draw (){
background (0);
spaceShip();
starsP2();
wormHole ();
score();
warpInitial();
blackHoleAt(100, 40);
blackHoleAt(400, 500);
}
//----------------------------------------------\\
//----------------------------------------------\\ starsRandom
void starsP1(){
int i = 0;
while (i < 100){
starXpos[i] = random(0, width);
starYpos[i] = random(0, height);
i = i + 1;
}
}
void starsP2(){
stroke(255);
strokeWeight(5);
int i = 0;
while (i < 100){
point(starXpos[i], starYpos[i]);
i = i + 1;
}
if (key == 'w'){
starYpos[i] = starYpos[i] + 1;
}
}
I'm trying to create a form of parallax for the stars in my code. When the user presses w,a,s,d the array of stars should correspond to the direction. I don't understand how this should work as I keep getting this error.
Try formatting your code to better see what's going on:
void starsP2(){
stroke(255);
strokeWeight(5);
int i = 0;
while (i < 100){
point(starXpos[i], starYpos[i]);
i = i + 1;
}
if (key == 'w'){
starYpos[i] = starYpos[i] + 1;
}
}
Your while loop executes until i == 100. Then after the while loop exits, you use that i variable again. Since i is 100, and your starYpos array only has up to index 99, you get an error.
The fix is to either move that if statement to inside the while loop, or to refactor your code so i doesn't go outside the bounds of the array.

Save image with Processing

I'm trying to save an image after certain time, the problem is that the image size is bigger than the display so when I use the save or saveFrame function it only saves the image that I can see in the display. There is any other way to save the whole image?
This is my code:
PImage picture, pictureFilter, img;
int total, cont, current;
ArrayList<ArrayList<Position>> columns;
String[] fontList;
public class Position {
public int x;
public int y;
}
void setup() {
fontList = PFont.list();
picture = loadImage("DSC05920b.JPG");
pictureFilter = loadImage("filtrePort2.jpg");
frame.setResizable(true);
size(picture.width, picture.height);
columns = new ArrayList<ArrayList<Position>>();
for(int i = 0; i < picture.width; i++) {
ArrayList<Position> row = new ArrayList<Position>();
for(int j = 0; j < picture.height; j++){
Position p = new Position();
p.x = i;
p.y = j;
row.add(p);
}
columns.add(row);
}
total = picture.width * picture.height;
cont = total;
current = 0;
img = createImage(picture.width, picture.height, RGB);
}
float randomLetter() {
float value = 23;
boolean found = false;
while(!found) {
value = random(48, 122);
if(value >48 && value <58) found = true;
if(value >65 && value <91) found = true;
if(value >97 && value <123) found = true;
}
return value;
}
void draw() {
int x = int(random(0, columns.size()));
ArrayList<Position> rows = columns.get(x);
int y = int(random(0, rows.size()));
Position p = rows.get(y);
color c = pictureFilter.get(p.x, p.y);
int r = (c >> 16) & 0xFF; // Faster way of getting red(argb)
if(r < 240) {
PFont f = createFont(fontList[int(random(0,fontList.length))],random(5, 24),true);
textFont(f);
fill(picture.get(p.x,p.y));
char letter = (char) int(randomLetter());
text(letter, p.x, p.y);
}
if(rows.size() == 1) {
if(columns.size() == 1) {
saveFrame("lol.jpg");
columns.remove(x);
} else {
columns.remove(x);
}
} else {
println(rows.size());
rows.remove(y);
}
--cont;
float percent = float(total-cont)/float(total)*100;
if(int(percent) != current) {
current = int(percent);
save("image_" + current + ".jpg");
}
println("DONE: " + (total-cont) + "/" + total + " Progress: " + percent + "%");
}
The code do a lot of stuff but the part that its not working well is at the final when I check if the percentage have been increased in order to save the image
You can write this into a PGraphics context - aka a graphics buffer.
The buffer can be as big as you need it to be, and you can choose whether to draw it on the screen or not..
// Create the buffer at the size you need, and choose the renderer
PGraphics pg = createGraphics(myImage.width, myImage.height, P2D);
// Wrap all your drawing functions in the pg context - e.g.
PFont f = createFont(fontList[int(random(0,fontList.length))],random(5, 24),true);
textFont(f);
pg.beginDraw();
pg.fill(picture.get(p.x,p.y));
char letter = (char) int(randomLetter());
pg.text(letter, p.x, p.y);
pg.endDraw();
// Draw your PG to the screen and resize the representation of it to the screen bounds
image(pg, 0, 0, width, height); // <-- this wont actually clip/resize the image
// Save it
pg.save("image_" + current + ".jpg");
The PImage class contains a save() function that exports to file. The API should be your first stop for questions like this.

Need to be able to see rectangles being drawn in Processing using for loop

For a project I made a code that creates a computer wallpaper with icons. One Icon I set to draw a loading bar when clicked (void mousePressed). I want to be able to see the rectangle(loading bar)start at a determined location using RectMode(CORNER) and have the width increase every few seconds until the bar is about 3/4 full and then stop and remain.
please give suggestions
this draws the finished bar but i want to see each increment for a couple seconds
void setup(){
size(800,600);
}
void mousePressed(){
if (mousePressed && mouseX>width/4 && mouseX<width-width/4 && mouseY>height/3 && mouseY<height- height/3){
rectMode(CORNER);
noStroke();
fill(0,180,0,180);
for( int r = 0; r <= 7; r++){
if (r == 1)
i = 50;
rect(width/2-348,height/2-35,i,height/8-4);
if (r == 2)
i = 150;
rect(width/2-348,height/2-35,i,height/8-4);
if (r == 3)
rect(width/2-348,height/2-35,i,height/8-4);
i = 250;
if (r == 4)
rect(width/2-348,height/2-35,i,height/8-4);
i = 350;
if (r == 5)
rect(width/2-348,height/2-35,i,height/8-4);
i = 450;
if (r == 6)
rect(width/2-348,height/2-35,i,height/8-4);
i = 550;
if (r == 7)
rect(width/2-348,height/2-35,i,height/8-4);
i = 650;
}
}
}
Using loop is in processing defined by function loop() and can be stopped by noLoop() also I am using frameCount (contains the number of frames that have been displayed since the program started - each run of draw() function) to count percentage of loaded progress bar and to stop loading on 3/4 as you want.
boolean loading = false;
int fillX = 0;
void setup()
{
size(300,300);
background(0);
noLoop();
}
void draw()
{
stroke(255);
fill(0);
rect(48, 137, 204, 25);
noStroke();
fill(255);
rect(51, 140, fillX, 20);
if(loading == true)
{
fillX = ((frameCount%301) / 3 * 2);
if(frameCount%(300*0.75) == 0)
{
loading = false;
noLoop();
frameCount = 0;
}
}
}
void mousePressed() {
loading = true;
loop();
}
RectMode(CORNER) is default mode so the is no need to specify it unless you are using different modes within project.
Do you want to do something like this?
int time, myWidth;
boolean loading;
void setup(){
size(800,600);
loading = false;
myWidth = 0;
}
void draw(){
drawLoadingBar();
}
void drawLoadingBar(){
if(myWidth < width/3){
if(loading && millis()-time > 1000){
rect(20, height/2, myWidth, 30);
myWidth = myWidth + 10;
time = millis();
}
}
}
void mousePressed(){
if(loading == false){
time = millis();
loading = true;
}
}
This code works by increasing the bar width by 10 every second after the first mouse click.

How to efficiently store past depth pixel data from depthMapRealWorld() method?

I can't get around a peculiar problem with SimpleOpenNI for Processing ao I'm asking for your help.
I'd like to store snapshots of pixel depth data (returned by .depthMapRealWorld() method as PVector arrays) on discrete time intervals, then process them further for a presentation. I tried adding them in an ArrayList, but it seems that the depthMapRealWorld() method is returning only a reference to a current depth data, not a real array. I tried in this sequence:
Just getting the data and adding it in an arraylist. On every call of the update() method the whole arraylist contained the same PVector array, even if the array at the zero position was added many iterations away!
Then I made the PVector array, along with its creation time, part of a class. Rewrote the sketch a little, but it didn't help. All of the arrays in the arraylist werw still the same.
Finally, in the constructor of the class, I "manually" copied the xyz coordinates of every vector from the PVector array into a int array. That seemed to solve the problem - the int arrays in the arraylist are now different from each other. But this solution introduced serious performance problems.
The question is: is there a more efficient way of storing these PVector arrays and retaining their value?
code:
import processing.opengl.*;
import SimpleOpenNI.*;
SimpleOpenNI kinect;
float rotation = 0;
int time = 0;
ArrayList dissolver;
ArrayList<Integer> timer;
int pSize = 10;
Past past;
void setup() {
dissolver = new ArrayList();
timer = new ArrayList();
size(1024, 768, OPENGL);
kinect = new SimpleOpenNI(this);
kinect.enableDepth();
translate(width/2, height/2, -100);
rotateX(radians(180));
stroke(255);
}
void draw() {
background(0);
translate(width/2, height/2, 500);
rotateX(radians(180));
kinect.update();
stroke (255, 255, 255);
past = new Past (kinect.depthMapRealWorld(), time);
if (dissolver.size() == pSize) { //remove the oldest arraylist element if when list gets full
dissolver.remove(0); //
}
if (time % 20 == 0) {
dissolver.add (past);
Past p1 = (Past) dissolver.get (0);
float [][] o2 = p1.getVector();
println ("x coord of a random point at arraylist position 0: " + o2[50000][0]); //for testing
}
if (dissolver.size() == pSize-1) {
//dissolve ();
}
time ++;
}
void dissolve () { //from the previous nonworking version; ignore
for (int offset = 0; offset < pSize-1; offset ++) {
PVector[] offPoints = (PVector[]) dissolver.get (offset);
int offTime = timer.get(offset);
for (int i = 0; i < offPoints.length; i+=10) {
int col = (time-offTime)*2; //why??
stroke (255, 0, col);
PVector currentPoint = offPoints[i];
if (currentPoint.z <1500) {
point(currentPoint.x, currentPoint.y, currentPoint.z); // - 2*(time-offTime) + random(0, 100)
}
}
}
}
class Past {
private PVector [] depth; //should contain this, not int
private float [][] depth1;
private int time;
Past (PVector [] now, int t) {
//should be like this: depth = now;
//clumsy and performancewise catastrophic solution below
depth1 = new float [now.length][3];
for (int i = 0; i< now.length; i+=10) {
PVector temp = now[i];
depth1 [i][0] = temp.x;
depth1 [i][1] = temp.y;
depth1 [i][2] = temp.z;
}
//arrayCopy(now, depth); this didn't work either
time = t;
}
float [][] getVector () {
return depth1;
}
int getTime () {
return time;
}
}
If I understood correctly, you want to store the 3D positions(ArrayList of PVectors) for each frame, right ?
If so, you should be able to simply store PVectors and reference them later.
Here's a basic sketch to illustrate this:
import processing.opengl.*;
import SimpleOpenNI.*;
SimpleOpenNI kinect;
ArrayList<ArrayList<PVector>> frames = new ArrayList<ArrayList<PVector>>();
ArrayList<PVector> frame;
boolean isRecording = true;
boolean isRecFrame;
void setup() {
size(1024, 768, OPENGL);
kinect = new SimpleOpenNI(this);
kinect.enableDepth();
stroke(255);
}
void draw() {
background(0);
translate(width/2, height/2, 500);
rotateX(PI);
translate(0,0,-1000);
kinect.update();
if(isRecording){
isRecFrame = (frameCount % 20 == 0);//record every 20 frames
int[] depthMap = kinect.depthMap();
int steps = 5; // to speed up the drawing, draw every N point
int index;
PVector realWorldPoint;
if(isRecFrame) frame = new ArrayList<PVector>();
for(int y=0;y < kinect.depthHeight();y+=steps)
{
for(int x=0;x < kinect.depthWidth();x+=steps)
{
index = x + y * kinect.depthWidth();
if(depthMap[index] > 0)
{
realWorldPoint = kinect.depthMapRealWorld()[index];
point(realWorldPoint.x,realWorldPoint.y,realWorldPoint.z);
if(isRecFrame) frame.add(realWorldPoint.get());
}
}
}
if(isRecFrame) frames.add(frame);
}else{//playback
ArrayList<PVector> currentFrame = frames.get(frameCount%frames.size());//playback is faster than recording now for testing purposes - add a decent frame counter here at some point
for(PVector p : currentFrame) point(p.x,p.y,p.z);
}
}
void keyPressed(){
if(key == ' ') isRecording = !isRecording;
}
Use the SPACE key to toggle between recording and playback.
The main thing to note is I'm storing a copy of the real world position for each depth pixel (frame.add(realWorldPoint.get());). Another thing to keep in mind is that currently you're storing these coordinates in memory which at some point will fill. If you only store a limited number of frames that should be fine, if not you might want to save to the points to disk. This way you can reuse recordings with other sketches. A basic way would be to sore them in a csv file:
void saveCSV(ArrayList<PVector> pts){
String csv = "x,y,z\n";
for(PVector p : pts) csv += p.x + "," + p.y + "," + p.z + "\n";
saveStrings("frame_"+frameCount+".csv",csv.split("\n"));
}
Another would be to use a more suitable format for point clouds, like PLY.
Saving an ASCII PLY is fairly straight forward:
void savePLY(ArrayList<PVector> pts){
String ply = "ply\n";
ply += "format ascii 1.0\n";
ply += "element vertex " + pts.size() + "\n";
ply += "property float x\n";
ply += "property float y\n";
ply += "property float z\n";
ply += "end_header\n";
for(PVector p : pts)ply += p.x + " " + p.y + " " + p.z + "\n";
saveStrings("frame_"+frameCount+".ply",ply.split("\n"));
}
You can later open/explore/process these files with tools like MeshLab.

Resources