I wrote a program in Procesisng that renders opaque cubes with random colour and rotation on top of each other, but I'm looking to individually continuously spin each cube while the program is running. Here's my code at the moment,
int boxval = 1;
void setup(){
size (640, 320, P3D);
frameRate(60);
}
void draw(){
for (int i = 0; i < boxval; i++){
translate(random(0,640), random(0,320), 0);
rotateY(random(0,360));
rotateX(random(0,360));
rotateZ(random(0,360));
fill(random(0,255),random(0,255),random(0,255),50);
noStroke();
box(64,64,64);
}
}
Here's a screenshot if it helps at all,
This is a great time to use Object Oriented Programming! If I understand the question correctly, you would like each cube to rotate independently of the other cubes. Let's make a Cube class. Think of each cube as an object that we will handle individually.
class Cube {
float x, y, z; // position of the cube
float size; // size of cube
color c; // color of cube
float xAngle, yAngle, zAngle; // current rotation amount of cube's x, y, z axes
float xSpeed, ySpeed, zSpeed; // how quickly the cube is rotated in the x, y, z axes
// Cube constructor - create the cube and all of its parameters
Cube(float x_, float y_, float z_, float size_, color c_, float xSpeed_, float ySpeed_, float zSpeed_) {
x = x_;
y = y_;
z = z_;
size = size_;
c = c_;
xSpeed = xSpeed_;
ySpeed = ySpeed_;
zSpeed = zSpeed_;
xAngle = yAngle = zAngle = 0; // starting position
}
// update the cube
// all we're doing is rotating each axis
void update() {
xAngle += xSpeed;
yAngle += ySpeed;
zAngle += zSpeed;
}
// draw the cube to the screen
void display() {
pushMatrix(); // need this
translate(x, y, z); // position on screen
rotateX(xAngle); // rotation amounts
rotateY(yAngle);
rotateZ(zAngle);
fill(c);
noStroke();
box(size);
popMatrix(); // and this
// push and pop matrix allows for individual cube rotation
// otherwise you would rotate the whole draw window, which isn't what you're looking for
}
}
If you would like each cube to change color and position on screen but still rotate independently, the display() function could be something like this instead:
void display() {
pushMatrix();
translate(random(0, width), random(0, height), random(-100, 100)); // random position on screen
rotateX(xAngle);
rotateY(yAngle);
rotateZ(zAngle);
fill(random(255), random(255), random(255), 50); // random color
noStroke();
box(size);
popMatrix();
}
Understanding rotation and translation of elements in Processing is really key. I highly recommend this tutorial from the Processing website if you have not read it. I incorporated some concepts into the Cube class.
Since you would like to have more than one Cube drawn on the screen, let's make an array of Cubes. I chose 25 as an arbitrary number.
Cube[] cube = new Cube[25];
Now in setup(), we'll need to actually create each Cube and give it certain parameters, like position on screen, color, etc. Here is how that is accomplished.
for (int i = 0; i < cube.length; i++) {
cube[i] = new Cube(random(0, width), random(0, height), 0, // x, y, z position
random(30, 80), color(random(255), random(255), random(255), 50), // size, color
random(0.001, 0.020), random(0.001, 0.020), random(0.001, 0.020)); // xSpeed, ySpeed, zSpeed
}
Now we just need to draw the Cubes to the screen and update the rotation of each one, which simply happens in the draw() loop.
for (int i = 0; i < cube.length; i++) {
cube[i].update();
cube[i].display()
}
Here is whole program. It's important to call background() each time through the draw() loop so the display window will be cleared each frame. Comment it out to see what will happen, but I noticed that was not in the code snippet you provided above. I guess it can be an effect though!
Cube[] cube = new Cube[25];
void setup() {
size(640, 320, P3D);
smooth();
frameRate(60);
for (int i = 0; i < cube.length; i++) {
cube[i] = new Cube(random(0, width), random(0, height), 0,
random(30, 80), color(random(255), random(255), random(255), 50),
random(0.001, 0.020), random(0.001, 0.020), random(0.001, 0.020));
}
}
void draw() {
camera();
lights();
background(50);
for (int i = 0; i < cube.length; i++) {
cube[i].update();
cube[i].display();
}
}
I'm not sure what your programming background is, but getting a hang of Object Oriented Programming is really helpful in Processing (and other OOP languages), so I'd recommend this OOP tutorial from the Processing website if you need a crash course. My programming life changed when OOP finally made sense.
Related
This is my first time writing here so i'll be direct, i've been trying to recreate this image:
and so far all the code i've got is:
void setup() {
size(500, 500);
}
void draw() {
rectMode(CENTER);
recta();
}
void recta() {
noFill();
int a = 10;
int y = 250;
for (int x = 0; x<20; x++) {
pushMatrix();
translate(y, y);
rect(0, 0, a, a);
popMatrix();
rotate(radians(2.0*PI));
stroke(0, 0, 0);
a= a - 20;
}
}
And i have no idea what to do next since this is what i get from it:
So i'd like to ask for help on how to get the same result as the image.
You are so close !
You're absolutely on the right track using pushMatrix()/popMatrix() to isolate coordinate systems, however you might have accidentally placed the rotation after popMatrix() which defeats the purpose. You probably meant to for each square to have an independent rotation from each other and not accumulate 2 * PI to the global rotation.
The other catch is that you're rotating by the same angle (2 * PI) for each iteration in your for loop and that rotation is 360 degrees so even if you fix rotation like this:
pushMatrix();
translate(y, y);
rotate(radians(2.0*PI));
rect(0, 0, a, a);
popMatrix();
you'll get a scaling effect:
(Minor note 2.0 * PI already exists in Processing as the TWO_PI constant)
To get that spiral looking effect is to increment the angle for each iteration (e.g. x = 0, rotation = 0, x = 1, rotation = 5, x = 2, rotation = 10, etc.). The angle increment is totally up to you: depending on how you map the x increment to a rotation angle angle you'll get a tighter or looser spiral.
Speaking of mapping, Processing has a map() function which makes it super easy to map from one range of numbers (let's say x from 0 to 19) to another (let's say 0 radians to PI radians):
for (int x = 0; x < 20; x++) {
pushMatrix();
translate(y, y);
rotate(map(x, 0, 19, 0, PI));
rect(0, 0, a, a);
popMatrix();
a = a - 20;
}
Here's a basic sketch based on your code:
int a = 10;
int y = 250;
void setup() {
size(500, 500);
rectMode(CENTER);
noFill();
background(255);
recta();
}
void recta() {
for (int x = 0; x < 20; x++) {
pushMatrix();
translate(y, y);
rotate(map(x, 0, 19, 0, PI));
rect(0, 0, a, a);
popMatrix();
a = a - 20;
}
}
I've removed draw() because it was rendering the same frame without any change: drawing once in setup() achieves the same visual effect using less CPU/power.
You can use draw(), but might as add some interactivity or animation to explore shapes. Here's a tweaked version of the above with comments:
int y = 250;
void setup() {
size(500, 500);
rectMode(CENTER);
noFill();
}
void draw(){
background(255);
recta();
}
void recta() {
// map mouse X position to -180 to 180 degrees (as radians)
float maxAngle = map(mouseX, 0, width, -PI, PI);
// reset square size
int a = 10;
// for each square
for (int x = 0; x < 20; x++) {
// isolate coordinate space
pushMatrix();
// translate first
translate(y, y);
// then rotate: order matters
// map x value to mouse mapped maximum rotation angle
rotate(map(x, 0, 19, 0, maxAngle));
// render the square
rect(0, 0, a, a);
popMatrix();
// decrease square size
a = a - 20;
}
}
Remember transformation order matters (e.g. translate() then rotate() would produce different effects compared to rotate() then translate()). Have fun!
I want to achieve a slow fade in size on every collapse into itself. In other words, when the circle is at its biggest, the ellipses will be at the largest in size and conversely the opposite for the retraction. So far I am trying to achieve this affect by remapping the cSize from the distance of the center point, but somewhere along the way something is going wrong. At the moment I am getting a slow transition from small to large in ellipse size, but the inner ellipses are noticeably larger. I want an equal distribution of size amongst all ellipses in relation to center point distance.
I've simplified the code down to 4 ellipses rather than an array of rows of ellipses in order to hopefully simplify this example. This is done in the for (int x = -50; x <= 50; x+=100).
I've seen one or two examples that slightly does what I want, but is more or less static. This example is kind of similar because the ellipse size gets smaller or larger in relation to the mouse position
Distance2D
Here is an additional diagram of the grid of ellipses I am trying to create, In addition, I am trying to scale that "square grid" of ellipses by a center point.
Multiple ellipses + Scale by center
Any pointers?
float cSize;
float shrinkOrGrow;
void setup() {
size(640, 640);
noStroke();
smooth();
fill(255);
}
void draw() {
background(#202020);
translate(width/2, height/2);
if (cSize > 10) {
shrinkOrGrow = 0;
} else if (cSize < 1 ) {
shrinkOrGrow = 1;
}
if (shrinkOrGrow == 1) {
cSize += .1;
} else if (shrinkOrGrow == 0) {
cSize -= .1;
}
for (int x = -50; x <= 50; x+=100) {
for (int y = -50; y <= 50; y+=100) {
float d = dist(x, y, 0, 0);
float fromCenter = map(cSize, 0, d, 1, 10);
pushMatrix();
translate(x, y);
rotate(radians(d + frameCount));
ellipse(x, y, fromCenter, fromCenter);
popMatrix();
}
}
}
The values you're passing into the map() function don't make a lot of sense to me:
float fromCenter = map(cSize, 0, d, 1, 100);
The cSize variable bounces from 1 to 10 independent of anything else. The d variable is the distance of each ellipse to the center of the circle, but that's going to be static for each one since you're using the rotate() function to "move" the circle, which never actually moves. That's based only on the frameCount variable, which you never use to calculate the size of your ellipses.
In other words, the position of the ellipses and their size are completely unrelated in your code.
You need to refactor your code so that the size is based on the distance. I see two main options for doing this:
Option 1: Right now you're moving the circles on screen using the translate() and rotate() functions. You could think of this as the camera moving, not the ellipses moving. So if you want to base the size of the ellipse on its distance from some point, you have to get the distance of the transformed point, not the original point.
Luckily, Processing gives you the screenX() and screenY() functions for figuring out where a point will be after you transform it.
Here's an example of how you might use it:
for (int x = -50; x <= 50; x+=100) {
for (int y = -50; y <= 50; y+=100) {
pushMatrix();
//transform the point
//in other words, move the camera
translate(x, y);
rotate(radians(frameCount));
//get the position of the transformed point on the screen
float screenX = screenX(x, y);
float screenY = screenY(x, y);
//get the distance of that position from the center
float distanceFromCenter = dist(screenX, screenY, width/2, height/2);
//use that distance to create a diameter
float diameter = 141 - distanceFromCenter;
//draw the ellipse using that diameter
ellipse(x, y, diameter, diameter);
popMatrix();
}
}
Option 2: Stop using translate() and rotate(), and use the positions of the ellipses directly.
You might create a class that encapsulates everything you need to move and draw an ellipse. Then just create instances of that class and iterate over them. You'd need some basic trig to figure out the positions, but you could then use them directly.
Here's a little example of doing it that way:
ArrayList<RotatingEllipse> ellipses = new ArrayList<RotatingEllipse>();
void setup() {
size(500, 500);
ellipses.add(new RotatingEllipse(width*.25, height*.25));
ellipses.add(new RotatingEllipse(width*.75, height*.25));
ellipses.add(new RotatingEllipse(width*.75, height*.75));
ellipses.add(new RotatingEllipse(width*.25, height*.75));
}
void draw() {
background(0);
for (RotatingEllipse e : ellipses) {
e.stepAndDraw();
}
}
void mouseClicked() {
ellipses.add(new RotatingEllipse(mouseX, mouseY));
}
void mouseDragged() {
ellipses.add(new RotatingEllipse(mouseX, mouseY));
}
class RotatingEllipse {
float rotateAroundX;
float rotateAroundY;
float distanceFromRotatingPoint;
float angle;
public RotatingEllipse(float startX, float startY) {
rotateAroundX = (width/2 + startX)/2;
rotateAroundY = (height/2 + startY)/2;
distanceFromRotatingPoint = dist(startX, startY, rotateAroundX, rotateAroundY);
angle = atan2(startY-height/2, startX-width/2);
}
public void stepAndDraw() {
angle += PI/64;
float x = rotateAroundX + cos(angle)*distanceFromRotatingPoint;
float y = rotateAroundY + sin(angle)*distanceFromRotatingPoint;
float distance = dist(x, y, width/2, height/2);
float diameter = 50*(500-distance)/500;
ellipse(x, y, diameter, diameter);
}
}
Try clicking or dragging in this example. User interaction makes more sense to me using this approach, but which option you choose really depends on what fits inside your head the best.
I am fast approaching several deadlines for my highschool graduation project so any advice you can give would be great. My project is to code a movie. The idea is to use processing to move the characters like tokens and also use code to animate things like rain and fire. Right now I am finding it very difficult to move images and/or rotate them. This is a big hurtle for my project. The current code I have for this is butchered and complicated but here it is.
Image of leading lady, Radial: https://www.dropbox.com/s/x3gvendnaeftapj/radialoutlinel.png
/*
Radialrolling
*/
PImage img; // Declare variable "a" of type PImage
float ballX = 10;
float ballY = 200;
float h = 300;
//create a variable for speed
float speedY = 2; // spped set to 0 in order to test rotating. Necessary for rolling motion
float speedX = 0.;
void setup() {
size(800,800);
smooth();
noStroke();
background(0, 0, 0);// Load the image into the program
// change the mode we draw circles so they are
// aligned in the top left
ellipseMode(CORNER);
img = loadImage("radialoutlinel.png");
}
void RadialRoll(){
rotate(0);//if this is anything but 0 ball will appear of screen
image(img, ballX, ballY, h, h); //create a continuos rotation using the new fun
//nctions in the draw things
}
void draw() {
//clear the background and set the fill colour
background(0);
fill(255);
//draw the circle in it's current position
// ellipse(ballX, ballY, h,h);
//add a little gravity to the speed
speedY = speedY + 0;
speedX = speedX + .02;
ballX = ballX + speedX;
RadialRoll();
if (ballX > width - h) {
// set the position to be on the floor
ballX = width - h;
// and make the y speed 90% of what it was,
// but in the opposite direction
speedX = speedX * -1;
//switch the direction
//speedY = speedY;
}
if (ballX > width - h) {
// set the position to be on the floor
ballX = width - h;
// and make the y speed 90% of what it was,
// but in the opposite direction
speedX = speedX * -1;
//switch the direction
//speedY = speedY;
}
else if (ballX <= 0) {
// if the ball hits the top,
// make it bounce off
speedX = -speedX;
}
if (ballY > height - h) {
// set the position to be on the floor
ballY = height - h;
// and make the y speed 90% of what it was,
// but in the opposite direction
speedY = speedY * -1;
//switch the direction
//speedY = speedY;
}
else if (ballY <= 0) {
// if the ball hits the top,
// make it bounce off
speedY = -speedY;
}
}
How can I move images on screen and rotate them with little hassle?
Thank you very much.
-TheIronHobo
First when you look at rotate() function it take radians (values from 0 to TWO_PI) as argument so when you want fluent rotation use something like this
rotate(counter*TWO_PI/360);
Where counter could be integer value increased in every draw() loop. But if you just add this to you code image will be rotating around point [0,0] (upper left corner) and you will not see image for 1/4 of the rotation. To better understanding this you should read this TUTORIAL then you could start with basic rotation:
PImage img;
int counter = 1;
void setup() {
size(800, 800);
smooth();
background(0, 0, 0);
img = loadImage("radialoutlinel.png");
imageMode(CENTER); //you can change mode to CORNER to see the difference.
}
void draw() {
background(0);
fill(255);
counter++;
translate(width/2, height/2);
rotate(counter*TWO_PI/360);
image(img, 0, 0, 300, 300);
}
Then if you want also move image from left to right side you will just adjust translate() first parameter.
I am new to Processing.js and need a little bit support with this issue. I have made a HTML-Canvas animation where I have lines with a curtain like behavior which can be seen here:
Click
this is made with a canvas plugin called Paper.js
I now want to get similar effect on processing but don't really know how to figure it out. My attempt was:
float x;
float y;
void setup() {
size(1024, 768);
strokeWeight(2);
background(0, 0, 0);
}
void mouseMoved() {
x = mouseX;
y = mouseY;
}
void draw() {
background(0);
line(50, 50, x += x - x/5, y += y - y/5);
stroke(255, 255, 255);
line(50, 700, x += x - x/15, y += y - y/15);
stroke(255, 255, 255);
line(75, 50, x += x - x/25, y += y - y/25);
stroke(255, 255, 255);
line(75, 700, x += x - x/35, y += y - y/35);
// and so on, would create it within a loop
}
So what I am trying to do is basically get the same effect which I have done in HTML and adapt it in Processing.js.
Thanks in advance.
I'd strongly recommend ignoring the paper.js and reimplementing this properly. We're seeing a sequence of lines that connect to a historical line of coordinates, based on mouse position, so let's just implement that:
class Point {
float x, y;
Point(float _x, float _y) { x=_x; y=_y; }}
// our list of historical points
ArrayList<Point> points;
// the horizontal spacing of our lines has fixed interval
float interval;
// how many lines do we want to draw?
int steps = 50;
void setup() {
size(500, 500);
// initialise the "history" as just the midpoint
points = new ArrayList<Point>();
for (int i=0; i<steps; i++) {
points.add(new Point(width/2, height/2));
}
// compute the horizontal interval, because it's
// width-dependent. Never hard code dependent values.
interval = width/(float)steps;
// the lower we set this, the slower it animates.
frameRate(60);
}
void draw() {
// white background, black lines
background(255);
stroke(0);
// for each historic point, draw two
// lines. One from height 0 to the point,
// another from height [max] to the point.
Point p;
for (int i=0; i<steps; i++) {
p = points.get(i);
line(interval/2 + i*interval, 0, p.x, p.y);
line(interval/2 + i*interval, height, p.x, p.y);
}
// when we move the mouse, that counts as a new historic point
points.remove(0);
points.add(new Point(mouseX, mouseY));
}
Sketch running in the browser: http://jsfiddle.net/M2LRy/1/
(You could speed this up by using a round-robin array instead of an ArrayList, but ArrayLists are pretty convenient here)
The code below draws a spiral using objects from a string array. Everything is fine, except that I would like the text objects to be drawn at a roughly 45 degree angle at each instance (based on the current x, y coordinates in the code below) rather than being drawn horizontally (when the text is horizontally drawn, it naturally overlaps with other text at concentrated points along the top & bottom of the curve). I researched some methods, but I'm still very new to all of this, and potential solutions have all evaded me.
String example = "";
String[] wordSet = split(example, " ");
float x, y;
float angle = 0;
float radiusSpiralLine = 10;
size (800, 800);
translate(width/2, height/2);
background(#ffffff);
smooth();
fill(0);
for (int i = 0; i < wordSet.length; i++) {
angle += .05;
radiusSpiralLine += .5;
x = cos(angle) * radiusSpiralLine;
y = sin(angle) * radiusSpiralLine;
textSize(9);
text(wordSet[i], x, y);
}
Here is tutorial to very similar problem. In basic you need to store projection matrix by pushMatrix() then translate and rotate according to position of letter on curve and then restore matrix by popMatrix(). I don't know how exactly do you want to rotate you text but just fold round your text() function like this maybe it will help you:
pushMatrix();
translate(x, y);
rotate(angle);
text(wordSet[i], 0, 0);
popMatrix();
First, you should start getting in the habit of wrapping code in the setup() and draw() functions. Since you're drawing a static image you don't need the draw() function, but I think it's good practice to have those two.
Now, what you are doing now is simply translating the words by a very small amount. Do the math:
x = cos(angle) * radiusSpiralLine; //cos(.05)*.5 = .499
y = sin(angle) * radiusSpiralLine; //sin(.05)*.5 = .024
That means they move less than a pixel, and they're not rotating at all.
What you need is your good ol' friend, the rotate() function.
Let's re-write code:
String example = "These are a bunch of words going around!";
String[] wordSet = split(example, " ");
float x, y;
float angle = 0;
void setup() {
size (800, 800);
background(#ffffff);
smooth();
fill(0);
pushMatrix();
translate(width/2, height/2); //Translate when you need to translate, not before
for (int i = 0; i < wordSet.length; i++) {
angle = PI/5; //Our good friends, radians
textSize(20); //What is this, text for ants? Change to 20
rotate(angle);
text(wordSet[i], 20, 0);
}
popMatrix();
}
void draw() {
}
First notice, the setup() and draw(). I like them there. It looks nicer, I think.
A couple of important things to note.
The effects of rotate() and translate() are on the canvas are cumulative.
We could have had the same effect in different ways:
for (int i = 0; i < wordSet.length; i++) {
angle = PI/5;
textSize(20);
rotate(angle); //always rotating by PI/5 ON TOP of previous rotation
text(wordSet[i], 20, 0);
}
//Everything from now on will still be rotated, we don't want that!
Slightly better, but not there yet:
for (int i = 0; i < wordSet.length; i++) {
angle += PI/5; //constantly increasing the angle
textSize(20);
pushMatrix(); //push a new canvas on top of everything
rotate(angle); //rotate by angle (which increases every loop)
text(wordSet[i], 20, 0);
popMatrix(); //pop the rotated canvas out, go back to original canvas
} //Things won't be rotated, but they'll still be translated, since translate() is outside of pushMatrix and popMatrix
Hope this helps.