I've been trying to make the texture ( the img ) to be visible only where wave form active is. But so far my attempts failed. I didn't quite understand the usage of vertex.
PImage img;
import ddf.minim.*;
Minim minim;
AudioPlayer song;
void setup()
{
size(800, 600,P2D);
minim = new Minim(this);
song = minim.loadFile("song.mp3");
song.play();
img = loadImage("img.jpg");
}
void draw()
{
background(0);
stroke(255);
for (int i = 0; i < song.bufferSize() - 1; i++)
{
beginShape();
texture(img);
vertex(0,height/2);
vertex(i, height-100 - song.right.get(i)*50);
vertex(i+1, height-100 - song.right.get(i+1)*50);
vertex(width,height/2);
vertex(0,height/2);
vertex(0,height/2+100);
endShape();
}
}
You're almost there:
you are are passing the x,y values for the vertex position which renders the shape
you are not passing the texture mapping u,v coordinates
Be sure to read the vertex() reference:
This function is also used to map a texture onto geometry. The texture() function declares the texture to apply to the geometry and the u and v coordinates set define the mapping of this texture to the form. By default, the coordinates used for u and v are specified in relation to the image's size in pixels, but this relation can be changed with textureMode().
It's unclear what shape you are trying to draw, but one simple thing you could do is pass the x,y coordinates as u,v coordinates as well (instead of just vertex(x,y); use vertex(x,y,u,v);):
PImage img;
import ddf.minim.*;
Minim minim;
AudioPlayer song;
void setup()
{
size(800, 600,P2D);
noStroke();
minim = new Minim(this);
song = minim.loadFile("song.mp3");
song.play();
img = loadImage("img.jpg");
}
void draw()
{
background(0);
stroke(255);
for (int i = 0; i < song.bufferSize() - 1; i++)
{
beginShape();
texture(img);
vertex(0,height/2, //vertex 0,x,y
0,height/2); //vertex 0,u,v
vertex(i, height-100 - song.right.get(i)*50, //vertex 1,x,y
i, height-100 - song.right.get(i)*50); //vertex 1,u,v
vertex(i+1, height-100 - song.right.get(i+1)*50, //vertex 2,x,y
i+1, height-100 - song.right.get(i+1)*50); //vertex 2,u,v
vertex(width,height/2, //vertex 3,x,y
width,height/2); //vertex 3,u,v
vertex(0,height/2, //vertex 4,x,y
0,height/2); //vertex 4,u,v
vertex(0,height/2+100, //vertex 5,x,y
0,height/2+100); //vertex 5,u,v
endShape();
}
}
Not tested, but the comments should help spot the difference.
Here's a super basic example of using vertex() with texture():
PImage img;
void setup(){
size(100,100,P2D);
//make a texture
img = createImage(50,50,RGB);
for(int i = 0 ; i < img.pixels.length; i++) {
int x = i % img.width;
int y = i / img.height;
if(x % 4 == 0 && y % 4 == 0){
img.pixels[i] = color(255);
}else{
img.pixels[i] = color(0);
}
}
img.updatePixels();
}
void draw(){
background(0);
//sampling different u,v coordinates (vertex 1 is mapped to mouse) for same x,y
beginShape();
texture(img);
vertex(0,0,0,0);
vertex(50,0,mouseX,mouseY);
vertex(50,50,50,50);
vertex(0,50,0,50);
endShape();
text("u:"+mouseX+"v:"+mouseY,5,height);
translate(50,0);
//mapping u,v to x,y coordinates
beginShape();
texture(img);
vertex(0,0,0,0);
vertex(50,0,50,0);
vertex(50,50,50,50);
vertex(0,50,0,50);
endShape();
}
Notice how the texture distorts when you move the mouse, as it controls vertex 1's texture coordinates. vertex(x,y,u,v) is very similar to vertex(x,y), but in addition to the coordinate where the vertex gets rendered on screen you also can control the coordinate of where the texture is sampled from.
As the reference mentions, by default textureMode() is image, meaning the u,v coordinates are in the image coordinates (from 0,0 to texture image width,height). There's another mode available: NORMAL in which the u,v sampling coordinates are normalised (between 0.0 and 1.0) is closer to what you might have spotted in 3D applications UV mapping features
Related
In Processing, I'm trying to animate a spinning polygon. In the background, I have a series of 50 triangles that act as a gradient. These are both created in my draw function. How do I ensure that the polygon keeps spinning, but the triangles stay in the background without having to keep re-rendering the 50 triangles? Perhaps there's a cleaner way to create this triangular gradient?
int n = 9;
float ceiling = 350;
float floor = 250;
float diff = (ceiling - floor)/2;
float per = 0;
float dir = -1;
float rate = 0.01;
void setup() {
size(800, 800);
background(125,25,25);
frameRate(30);
}
void draw() {
background(125,25,25);
// Creates the triangles in background
for (float k=0; k<50; k++) {
strokeWeight(1);
stroke(#5E4622);
fill(47,74,57,100*(k/50));
triangle(100,height,width-100,height,width/2,height*k/50);
}
stroke(0);
// Creates spinning nonagons
pushMatrix();
translate(width/2, height/2);
rotate(2*PI*(dir*per));
stroke(#F4EA4A);
strokeWeight(6);
noFill();
polygon(0,0,floor+(diff*sin(2*PI*per))+10,n);
stroke(0);
strokeWeight(3);
float[] vertices = polygon(0, 0, floor+(diff*sin(2*PI*per)), n);
connect(vertices);
per += rate;
popMatrix();
}
// Takes a center (x,y) and draws an n-gon of radius r around it
// Returns an array of floats representing the points of the polygon
// Like: {x1,y1,x2,y2,...,xn,yn}
float[] polygon(float x, float y, float r, int n) {
float angle = 2*PI/n;
float[] vertices = new float[2*n];
beginShape();
for (int i=0; i<n; i++) {
float vX = r*cos(i*angle) + x;
float vY = r*sin(i*angle) + y;
vertex(vX, vY);
vertices[2*i] = vX;
vertices[2*i+1] = vY;
}
endShape(CLOSE);
return vertices;
}
// Takes in an array of vertices of a polygon and connects them together.
// Ignores neighboring vertices when considering which vertices to connect
// to a vertex.
void connect(float[] vertices) {
int n = vertices.length / 2;
for (int i=0; i<n; i++) {
float x = vertices[2*i];
float y = vertices[2*i+1];
for (int j=0; j<n; j++) {
if (j!=i || j!=(i-1)%n || j!=(i+1)%n) {
float endX = vertices[2*j];
float endY = vertices[2*j+1];
line(x, y, endX, endY);
}
}
}
}
This code creates what I want, but it runs pretty choppily due to having to re-render the triangles
How do I ensure that the polygon keeps spinning, but the triangles stay in the background without having to keep re-rendering the 50 triangles?
Render the static background to a PGraphics at initialization, in the setup function:
PGraphics pg;
void setup() {
size(800, 800);
// Creates the triangles in background
pg = createGraphics(800, 800);
pg.beginDraw();
pg.background(125,25,25);
for (float k=0; k<50; k++) {
pg.strokeWeight(1);
pg.stroke(#5E4622);
pg.fill(47,74,57,100*(k/50));
pg.triangle(100,height,width-100,height,width/2,height*k/50);
}
pg.endDraw();
frameRate(30);
}
Draw the background image to the scene by image(), in every frame, instead of filling the background by background():
void draw() {
// background image to screen
image(pg, 0, 0);
stroke(0);
// Creates spinning nonagons
// ...
}
Perhaps there's a cleaner way to create this triangular gradient?
If you want to get a smooth gradient background and get rid of the lines, then use pg.noStroke() rather than of pg.stroke(#5E4622);.
Additionally vary the size of the triangle on ist base, too:
for (float k=0; k<50; k++) {
pg.noStroke();
pg.fill(47,74,57,100*(k/50));
pg.triangle(k/50*width/2,height,width-k/50*width/2,height,width/2,height*k/50);
}
I am trying to rotate an OBJ from maya around an axis in Maya. It works just fine with a sphere, but with my own object - it is following an orbit. Maybe I don't understand the shape(parameters).
PShape s;
float theta = 0;
void setup() {
size(500, 500, P3D);
shapeMode(CENTER);
s = loadShape("obj2.obj");
}
void draw() {
background(32);
lights();
float z = 0;
pushMatrix();
translate(0,height*1/4);
rotateY(theta);
theta += .01;
scale(4.0);
box(100);
//shape(s, 0,0);
popMatrix();
}
here is the object: https://drive.google.com/open?id=0B3ddDpsAjuqPYUR6RHd0OFBfVU0
Take out this line of code:
shapeMode(CENTER);
For some reason, this line of code is causing the offset you're seeing. I'm not sure exactly why this causes the offset, but getting rid of it seems to fix your problem.
There is a good simple example of loading and displaying a 3d shape in the examples that come with the Processing editor. Just go to File > Examples and then go to Basics > Shape > LoadDisplayOBJ.
Kevin is right, part of the problem is shapeMode(CENTER).
Additionally you may want to double check if the mesh is centered in your editor.
I've imported your mesh in Blender, and although there is a difference in scale, the origin of your geometry was not at 0,0,0
Here's a tweaked version of your .obj and .mtl exported from Blender after manually translating the mesh so it's closer to the center:
PShape s;
float theta = 0;
void setup() {
size(500, 500, P3D);
s = loadShape("coral.obj");
}
void draw() {
background(32);
lights();
float z = 0;
pushMatrix();
translate(width * .5,height* .5);
rotateY(theta);
theta += .01;
scale(50.0);
shape(s, 0,0);
popMatrix();
}
Additionally you can manually compute the mesh bounding box and centroid to orbit around that position, or look a library that provides this functionality.
I cant figure this out. I have a sketch with little rotating rectangles on it. They rotate on every draw(). However the previous rectangle remains visible. I tried moving background() around but it either gets rid of all the rectangles apart from one or it doesn't clear the screen. I would like to be able to clear all the rectangles after each draw.
Here is the code:
//Create array of objects
ArrayList<Circle> circles = new ArrayList<Circle>();
ArrayList<Connector> centrePoint = new ArrayList<Connector>();
void setup(){
size(800, 800);
frameRate(1);
rectMode(CENTER);
background(204);
for(int i = 1; i < 50; i++){
float r = random(100,height-100);
float s = random(100,width-100);
float t = 20;
float u = 20;
println("Print ellipse r and s " + r,s);
circles.add(new Circle(r,s,t,u,color(14,255,255),random(360),random(5),random(10)));
}
//Draw out all the circles from the array
for(Circle circle : circles){
circle.draw();
float connectStartX = circle.x1;
float connectStartY = circle.y1;
println("PrintconnectStartX and Y " + connectStartX,connectStartY);
for(Circle circleEnd : circles){
float connectEndX = (circleEnd.x1);
float connectEndY = (circleEnd.y1);
centrePoint.add(new Connector(connectStartX,connectStartY,connectEndX,connectEndY));
}
}
//For each ellipse, add the centre point of the ellipse to array
for(Connector connectUp : centrePoint){
println(connectUp.connectStartX ,connectUp.connectStartY ,connectUp.connectEndX ,connectUp.connectEndY);
stroke(100, 0, 0);
if (dist(connectUp.connectStartX ,connectUp.connectStartY ,connectUp.connectEndX ,connectUp.connectEndY) < 75){
connectUp.draw(connectUp.connectStartX ,connectUp.connectStartY ,connectUp.connectEndX ,connectUp.connectEndY);
}
}
//For the line weight it should equal the fat of the node it has come from ie
//for each circle, for each connectUp if the x==connectStartX and y==connectStartY then make the line strokeWeight==fat
for(Circle circle : circles){
for(Connector connectUp : centrePoint){
if (connectUp.connectStartX == circle.x1 & connectUp.connectStartY == circle.y1 & (dist(connectUp.connectStartX ,connectUp.connectStartY ,connectUp.connectEndX ,connectUp.connectEndY) < 75)){
print(" true "+ circle.fat);
float authority = circle.fat;
strokeWeight(authority*1.5);
connectUp.draw(connectUp.connectStartX ,connectUp.connectStartY ,connectUp.connectEndX ,connectUp.connectEndY);
}
}
}
}
void update(){
}
void draw() {
for(Circle circle : circles){
circle.rot =+0.02;
circle.draw();
circle.rot = random(-6,6);
}
}
//Need to connect each ellipse to all the other ellipses
class Connector {
public float connectStartX;
public float connectStartY;
public float connectEndX;
public float connectEndY;
public color cB;
public float thickness;
public Connector(float connectStartX, float connectStartY, float connectEndX, float connectEndY){
this.connectStartX = connectStartX;
this.connectStartY = connectStartY;
this.connectEndX = connectEndX;
this.connectEndY = connectEndY;
//this.cB = tempcB;
//this.thickness = thickness;
}
void draw(float connectStartX, float connectStartY, float connectEndX, float connectEndY){
line(connectStartX, connectStartY, connectEndX, connectEndY);
// float fat = random(255);
//fill(fat);
stroke(100, 0, 0);
}
}
class Circle{
public float x1;
public float y1;
public float x2;
public float y2;
public color cB;
public float rot;
public float fat = random(5);
public float fert = 0.1;
public Circle(float x1, float y1, float x2, float y2, color tempcB, float rot, float fat, float fert){
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.cB = tempcB;
//Tilt - I think this is done in radians
this.rot = rot;
//Authority -this is the fill
this.fat = fat;
//Fertility- this is a multiplier for the tilt
this.fert = fert;
}
void draw(){
pushMatrix();
translate(x1, y1);
fert = random(0.5);
rot = random(-6,6);
rotate(rot*fert);
translate(-x1, -y1);
//float fat = random(255);
fill(fat);
rect(x1, y1, 24, 36);
popMatrix();
}
}
You've got a few things going on in your code that I've seen in your previous posts. The way you're doing your drawing doesn't make a ton of sense, and I'll explain why.
Here's what most Processing sketches do:
Use the setup() function to setup any data structures you'll use in your program. Don't do any drawing from the setup() function.
Call background() every frame to clear out old frames.
Draw everything you want to be drawn in the frame in the draw() function.
Modify the data structures to change what you're drawing on the screen.
Your code is a bit too long for an MCVE, so here's a little example that handles the drawing in a more standard way:
ArrayList<PVector> circles = new ArrayList<PVector>();
void setup() {
size(500, 500);
ellipseMode(RADIUS);
//setup your data structures here
circles.add(new PVector(250, 250));
//don't do any drawing yet
}
void mousePressed() {
//modify the data structure whenever you want to change what's on the screen
circles.add(new PVector(mouseX, mouseY));
}
void keyPressed() {
//modify the data structure whenever you want to change what's on the screen
if (!circles.isEmpty()) {
circles.remove(0);
}
}
void draw() {
//call background every frame to clear out old frames
background(0);
//draw everything
for (PVector p : circles) {
ellipse(p.x, p.y, 20, 20);
}
}
Notice how this is different from what you're doing. Here's what you do:
You use the setup() function to setup your data structures, but then you draw the background and some of the objects to the screen.
You then don't call background() from draw(), so you're always stuck with whatever has already been drawn.
You then only draw a subset of what you want on the screen, so you can't redraw your whole scene.
You have to modify your code to no longer draw anything from setup(), to call the background() function every frame, and to draw everything you want on the screen every frame.
What you are doing is printing every single circle or line...ect. You need to have a timer that removes them every so often. If you do it too fast you get a strobe like look. So have a timer that removes the first rect from the array list every so often.
Hello people of stackflow,
I'm new to processing but fairly familiar with coding.
For a school project, i'm making an interactive installation where the visitor is able to play with his "shadow".
They should be able to draw objects like wings or capes onto his shadow. These objects then need to move along with the skeleton of the player.
For instances, if i draw a big hat on my head it needs to move along with my head.
Now i made this simple code wich makes a silhouet of the player and the player is than able to draw on it and save screenshots.
import SimpleOpenNI.*;
SimpleOpenNI context;
PImage userImage;
int[] userMap;
PImage rgbImage;
PGraphics pg;
color pixelColor;
int dikte = 10;
void setup(){
size(1024,768);
context=new SimpleOpenNI(this);
context.enableRGB();
context.enableDepth();
context.enableUser();
pg = createGraphics(1024,768);
background(255);
userImage=createImage(640,480,RGB);
}
void draw(){
pg.beginDraw();
pg.strokeWeight(dikte);
if (mousePressed && (mouseButton == LEFT) == true) {
pg.stroke(0);
pg.line(mouseX, mouseY, pmouseX, pmouseY);
}
if (mousePressed && (mouseButton == RIGHT) == true) {
pg.stroke(255);
pg.line(mouseX, mouseY, pmouseX, pmouseY);
}
context.update();
rgbImage=context.rgbImage();
userMap=context.userMap();
for(int y=0;y<context.depthHeight();y++){
for(int x=0;x<context.depthWidth();x++){
int index=x+y*640;
if(userMap[index]!=0){
pixelColor=rgbImage.pixels[index];
userImage.pixels[index]=color(0,0,0);
}else{
userImage.pixels[index]=color(255);
}
}
}
userImage.updatePixels();
pg.endDraw();
image(userImage, 0, 0);
image(pg, 0, 0);
}
void keyPressed() {
if (key == CODED) {
if (keyCode == UP) {
//Dit maakt de screenshot
saveFrame("line-######.png");
}
if (keyCode == DOWN) {
//clear the drawings
pg.clear();
background(255);
}
if (keyCode == RIGHT && dikte<30) {
//adjust the stroke weight
dikte++;
}
if (keyCode == LEFT && dikte>2) {
//adjust the stroke weight
dikte--;
}
}
}
Now i have tested and inspected these codes, but i'm not able to change it so that the skeletons uses the draw function to use that as the limb.
void draw(){
//clears the screen with the black color, this is usually a good idea
//to avoid color artefacts from previous draw iterations
background(255);
//asks kinect to send new data
context.update();
//retrieves depth image
PImage depthImage=context.depthImage();
depthImage.loadPixels();
//get user pixels - array of the same size as depthImage.pixels, that gives information about the users in the depth image:
// if upix[i]=0, there is no user at that pixel position
// if upix[i] > 0, upix[i] indicates which userid is at that position
int[] upix=context.userMap();
//colorize users
for(int i=0; i < upix.length; i++){
if(upix[i] > 0){
//there is a user on that position
//NOTE: if you need to distinguish between users, check the value of the upix[i]
img.pixels[i]=color(0,0,255);
}else{
//add depth data to the image
img.pixels[i]=depthImage.pixels[i];
}
}
img.updatePixels();
//draws the depth map data as an image to the screen
//at position 0(left),0(top) corner
image(img,0,0);
//draw significant points of users
//get array of IDs of all users present
int[] users=context.getUsers();
ellipseMode(CENTER);
//iterate through users
for(int i=0; i < users.length; i++){
int uid=users[i];
//draw center of mass of the user (simple mean across position of all user pixels that corresponds to the given user)
PVector realCoM=new PVector();
//get the CoM in realworld (3D) coordinates
context.getCoM(uid,realCoM);
PVector projCoM=new PVector();
//convert realworld coordinates to projective (those that we can use to draw to our canvas)
context.convertRealWorldToProjective(realCoM, projCoM);
fill(255,0,0);
ellipse(projCoM.x,projCoM.y,10,10);
//check if user has a skeleton
if(context.isTrackingSkeleton(uid)){
//draw head
PVector realHead=new PVector();
//get realworld coordinates of the given joint of the user (in this case Head -> SimpleOpenNI.SKEL_HEAD)
context.getJointPositionSkeleton(uid,SimpleOpenNI.SKEL_HEAD,realHead);
PVector projHead=new PVector();
context.convertRealWorldToProjective(realHead, projHead);
fill(0,255,0);
ellipse(projHead.x,projHead.y,10,10);
//draw left hand
PVector realLHand=new PVector();
context.getJointPositionSkeleton(uid,SimpleOpenNI.SKEL_LEFT_HAND,realLHand);
PVector projLHand=new PVector();
context.convertRealWorldToProjective(realLHand, projLHand);
fill(255,255,0);
ellipse(projLHand.x,projLHand.y,10,10);
}
}
}
</pre>
Can someone please help me out with this,
kind regards
I am trying to rotate a line around in a circle that represents the direction a sensor is facing, while also plotting distance measurements. So I can't use background() in the draw function to clear the screen, because it erases the plotting of the distance readings. I've tried pggraphics and a few others ways, but can't seem to find a way to do it.
This is what I have right now:
void setup() {
background(255,255,255);
size(540, 540);
}
void draw() {
translate(width/2, height/2);
ellipse(0,0,100,100);
newX = x*cos(theta)- y*sin(theta);
newY = x*sin(theta)+ y*cos(theta);
theta = theta + PI/100;
//pushMatrix();
fill(255, 255);
line(0, 0, newX, newY);
rotate(theta);
//popMatrix();
}
I am new to Processing, and coding in general, but can anyone point me in the right direction on how to do this? Thanks
This is what it outputs: http://imgur.com/I825mjE
You can use background(). You just need to redraw the readings on each frame. You could store the readings in an ArrayList, which allows you to add new readings, change them and remove them.
An example:
ArrayList<PVector> readings;
int readingsCount = 15;
void setup() {
size(540, 540);
// create collection of random readings
readings = new ArrayList<PVector>();
for(float angle = 0; angle < TWO_PI; angle += TWO_PI/ readingsCount) {
float distance = random(100, 200);
// the new reading has an angle...
PVector newReading = PVector.fromAngle(angle);
// ... and a distance
newReading.mult(distance);
// Add the new reading to the collection
readings.add(newReading);
}
}
void draw() {
background(255);
// Put (0, 0) in the middle of the screen
translate(width/2, height/2);
float radius = 250;
noFill();
ellipse(0, 0, 2*radius, 2*radius);
// draw spinning line
float angle = frameCount * 0.1;
line(0, 0, radius * cos(angle), radius * sin(angle));
// draw readings
for(PVector p : readings) {
ellipse(p.x, p.y, 20, 20);
}
}