I'm working on a 3D scene in Java using the Processing API. It's a force-directed graph layout algorithm (although that isn't too important). I've got all the graph drawing done -- the nodes, edges, layout, etc. are looking good. Each node on the graph has a label, though, and I'd like to be able to display said label as text next to the node. I've tried working with the text() function, but so far it seems like my code just doesn't work. I see no text anywhere in the scene.
My code looks like the following:
pushMatrix();
translate(width/2, height/2, 0); // put 0,0,0 at the center of the screen
text("foo!", 20, 20, 20);
popMatrix();
And I don't see anything. Just the graph. So what am I missing?
Everything is fine with the tiny bit of code you displayed. You can see a modified version running here:
void setup() {
size(400,400,P3D);
textSize(20);
}
void draw() {
background(0);
translate(width * .5, height*.5,0);
rotateY(map(mouseX,0,width,-PI,PI));
rotateX(map(mouseY,0,height,-PI,PI));
pushMatrix();
text("foo!", -20, 0, 20);
popMatrix();
}
There might be something else along the way. Care to share more information ?
The fill color controls the text color, and defaults to white. So if you are painting white text on a white background, it won't show up. Add fill(0); before you draw text.
Also remember that shapes drawn after you send your text to the screen may over-write your text. The last 'hidden' statement in draw is to paint the screen.
Here's an example of drawing a series of vertical lines (in 2D) with a row of labels at the top:
int startX;
void setup() {
size(400,400);
textSize(12);
startX = width/10;
}
void draw() {
background(255);
int curX = startX;
fill(0); // Set the text color
while (curX < width)
{
line(curX, 30, curX, height-10);
text(curX, curX-(curX/20), 20);
curX += width/10;
}
} // end draw
Related
I'm a total beginner so forgive me if this is probably silly or improper of me to ask.
I'm trying to make my own virtual oscillograph in processing. I don't really know how to explain it, but I want to "zoom out" from where I am getting the peaks in waveforms, which is the window size. I'm not sure what I'm doing wrong here or what's wrong with my code. I've tried changing the buffer size, and changing the multiplier for x/y. My sketch is adapted from a minim example Sketch.
All Help is greatly appreciated.
import ddf.minim.*;
Minim minim;
AudioInput in;
int frames;
int refresh = 7;
float fade = 32;
void setup()
{
size(800, 800, P3D);
minim = new Minim(this);
ellipseMode(RADIUS);
// use the getLineIn method of the Minim object to get an AudioInput
in = minim.getLineIn(Minim.STEREO);
println (in.bufferSize());
//in.enableMonitoring();
frameRate(1000);
background(0);
}
void draw()
{
frames++; //same saying frames = frames+1
if (frames%refresh == 0){
fill (0, 32, 0, fade);
rect (0, 0, width, height);
}
float x;
float y;
stroke (0, 0);
fill (0,255,0);
// draw the waveforms so we can see what we are monitoring
for(int i = 0; i < in.bufferSize() - 1; i++)
{
x = width/2 + in.left.get(i) * height/2;
y = height/2- in.right.get(i) * height/2;
ellipse(x, y, .5, .5);
}
}
Thanks
Edit: you don't need push and pop matrix here. Guess my understanding of it is lacking too. You can just use translate.
You can use matrices to create a camera object, there is tons of material out there that you can read up on to understand the math behind this and implement it anywhere.
However, there might be an easier solution here. You can use pushMatrix and popMatrix in combination with translate. Push and popping the matrix will manipulate the matrix stack - you create a new "frame" where you can play around with translations, then pop back the original frame (so you don't get lost by applying new translations on each frame).
push the matrix, translate the z coordinate once before drawing everything you want zoomed out, pop the matrix. You can set up a variable for the translation so that you can control this with your mouse.
Here's a crude example (I don't have all those libraries so couldn't add it to your code):
float scroll = 0;
float scroll_multiplier = 10;
void setup()
{
size(800, 800, P3D);
frameRate(1000);
background(0);
}
void draw()
{
background(0);
//draw HUD - things that don't zoom.
fill(255,0,0);
rect(400,300,100,100);
//We don't want to mess up our coordinate system, we push a new "frame" on the matrix stack
pushMatrix();
//We can now safely translate the Y axis, creating a zoom effect. In reality, whatever we pass to translate gets added to the coordinates of draw calls.
translate(0,0,scroll);
//Draw zoomed elements
fill(0,255,0);
rect(400,400,100,100);
//Pop the matrix - if we don't push and pop around our translation, the translation will be applied every frame, making our drawables dissapear in the distance.
popMatrix();
}
void mouseWheel(MouseEvent event) {
scroll += scroll_multiplier * event.getCount();
}
Using FX2D.
Hi, I'm currently drawing a line at every frame using the curveVertex() function.
Every line stays on the sketch voluntarily by not resetting the background at every step,
which leaves a trail effect.
But I would like to make these trails fade away over time. I tried resetting the background in the draw() function by giving it a small opacity value but it clears all the trails at once every time.
Right now I can only have either all trails or no trails.
//background(0, 0, 0, 10); // Reset background every time
stroke(255, 255, 255, 10); // Draw Line between all nodes
curveVertex(nodes.get(fixId(i)).position.x, nodes.get(fixId(i)).position.y);
with trails
background() does not just set the background color, it clear the entire window. It is not intended to use background within beginShape() / endShape() sequences.
What what to do can be achieved by drawing a rect() with blendMode(DIFFERENCE) on the entire window, at the begin of the frame. e.g.:
void draw() {
// "fade" the entire view
blendMode(DIFFERENCE);
fill(1, 1, 1, 255);
rect(0, 0, width, height);
blendMode(ADD);
// draw shape
// [...]
}
See also the answer to Processing - rendering shapes.
Im writing a 3D sketch in which the user rotates the camera with peasyCam while left clicking and moving the mouse. The thing is that I want to move the objects while right click is pressed so that the user can drag the object across the screen's X and Y axis. Of course I know how to use mouseX and mouseY inputs to modify the translation but only across the 3D space coordinates as it shows on the GIF below:
example code of whats happening in the image:
import peasy.*;
import peasy.org.apache.commons.math.*;
import peasy.org.apache.commons.math.geometry.*;
PeasyCam cam;
float x=15;float y=15; float z=15;
float e;
void setup(){
size (700,700,P3D);
cam = new PeasyCam(this, 200);
cam.setRightDragHandler(null);
}
void draw(){
background(0);
pushMatrix();
translate(5, 5, 0);
fill(255);
stroke(255);
sphere(5);
popMatrix();
pushMatrix();
fill(255,0,0);
stroke(255,0,0);
translate(x, y, z);
sphere(5);
popMatrix();
stroke(0,0,255);
line(5,5,0,x,y,z);
//obvoiusly not working method
if(mousePressed && (mouseButton == RIGHT)){
x= x+(mouseX-pmouseX);
y= y+(mouseY-pmouseY);
}
}
void mouseWheel(MouseEvent event) {
e = event.getCount();
z=z+e;
println(e);
}
void mousePressed(){
if (mouseButton==RIGHT){
cam.setActive(false);
}
}
void mouseReleased(){
cam.setActive(true);
}
What I would need is to be able to drag the sphere only on the screens X/Y axis, at a fixed Z just like image below shows(simple simulation I made of the behaviour im looking for).
PeasyCam is for exploring the 3D space. The question might be difficult to undesrtand. The problem is about moving the object on the 3D world, using the screen/canvas 2D coordinates to make the object follow the cursor's movement. If the mouse goes to the left (x axis decreases), the object should move to the left on the screen, and not just on the worlds X axis. This is how the second example image behaves, but achieved by just simulating the 3D space with no actual rotations to the x,y,z axis.
I've been scratching my head with this thing and I cant seem to figure it out. I wouldn't have asked here otherwise. Thanks in advance guys.
PeasyCam is a library that gives you a camera that by default is controlled by the mouse. This allows you to render 3D scenes and not worry about the camera, since the library handles it for you.
But it sounds like that's not what you want. You want to render a 3D scene and use the mouse to control the position of the shapes in that scene. Basically, your controls are fighting with the default controls provided by the PeasyCam library.
I see that you've already tried disabling the right-click controls here:
cam.setRightDragHandler(null);
So at the very least you probably want to do the same thing with the left drag handler.
But at that point, why are you using the PeasyCam library at all?
And even if you disable the default left controls, you'll notice that the dragging of shapes is "exaggerated" because the camera is closer to the red shape, so moving it a little bit looks like it's moving more. Just like an object right in front of your face looks like it's moving a lot more than an object that's far away.
It sounds like what you really want to do is get rid of the PeasyCam library, and then use standard Processing functions to calculate the position of the spheres based on the user input. Check out the modelX(), modelY(), and modelZ() function in the reference.
Edit: Here is a simple example that shows the model functions in action:
float x;
float y;
void setup() {
size (700, 700, P3D);
}
void draw() {
background(0);
pushMatrix();
translate(width/2, height/2, 0);
fill(255);
stroke(255);
sphere(5);
popMatrix();
fill(255, 0, 0);
stroke(255, 0, 0);
if (mousePressed) {
x= modelX(mouseX, mouseY, 0);
y= modelY(mouseX, mouseY, 0);
}
translate(x, y, 15);
sphere(5);
}
May be you should be looking in beginHUD() and endHUD();
Here is the example code:
(Code from https://forum.processing.org/one/topic/2-questions-on-camera-view.html)
import peasy.*;
PeasyCam cam;
void setup() {
size(300,200,P3D);
// either put it here like this:
// cam = new PeasyCam(this, 50, 0, 0, 100);
cam = new PeasyCam(this, 0, 0, 0, 100);
cam.setMinimumDistance(50);
cam.setMaximumDistance(500);
// or separate like this:
cam.lookAt(50,0,0);
}
void draw() {
background(0);
//3D object
pushMatrix();
fill(255,0,0);
translate(50,0,0);
rotateX(-.5);
rotateY(-.5);
box(30);
popMatrix();
//2D object that is not affected by the camera
cam.beginHUD();
fill(0,0,255);
rect(200, height/2 -25 , 50, 50);
cam.endHUD();
}
I am currently working on a small project where I'm creating a simple boardgame-like spinning wheel. The user will press a button and the spinner will randomly land on one of the four colors (red, green, yellow, or blue). The trouble I'm having is getting the spinner to rotate in a circle (or clockwise) and randomly land in a random position in one of the four squares.
Screenshot of game thus far
And source code:
void setup() { // this is run once
size(800, 800);
}
void draw() { // this is run repeatedly
background(255);
strokeWeight(2);
fill(255,0,0);
rect(100,100,300,300);
fill(0,96,255);
rect(100, 400, 300, 300);
fill(255,240,0);
rect(400, 100, 300, 300);
fill(0,255,0);
rect(400, 400, 300, 300);
// how to rotate this part like a spinner?
strokeWeight(20);
line(400, 400, 400, 600);
}
I then need to figure out how to determine which color the spinner landed on, and print out text that says "You have landed on [the color the spinner lands on]". I am having difficulty understanding the Matrix aspect of determining the coordinates after the rotation.
I am coding in Java in the Processing development platform.
Unfortunately, working with both circles and coordinates can be a little tricky in programming. You're going to have to do some conversion between Polar and Cartesian coordinates.
Here's a great reference to the difference between the two.
So you'll need to first generate a random number between 0 and 2 PI (Radians), this is done easily in processing:
float rnd = random(0, TWO_PI);
Next need let's convert it to normal coordinates:
float x = 200 * cos(rnd);
float y = 200 * sin(rnd);
Lastly draw the line: line(400, 400, x + 400, y + 400);
Edit: Forgot processing had rotate(), that'd be a much better solution than this mess
Your first step will be to learn about rotations that are isolated to one shape without rotating the entire sketch. There's a code pattern involving pushMatrix, popMatrix, translate, and rotate - all in conjunction with one another.
// inside draw
pushMatrix();
translate(400, 400);
rotate(radians(rotation));
line(0, 0, 100, 100);
popMatrix();
rotation += 5;
The translate function moves the origin to a new position, in this case 400, 400. Any shapes drawn after the origin moves are relative to it. That is the reason line is drawn at 0, 0 on the new origin which is actually 400, 400. The functions pushMatrix and popMatrix isolate this code so as not to affect the rest of your sketch. It's a nice trick to create independent rotations (and anything else really) in your sketch without having to come up with math formulas to counteract all your movements. Imagine five spinners going different speeds and directions.
For a gradually slowing spinner, I introduce a stepSize variable and slowly decrease it and subtract it from rotation until rotation hits zero and the spinner stops.
// still inside draw
if (stepSize > 0) {
rotation += stepSize;
stepSize -= 0.05; // play around with this value
}
Here's a demo program putting all the pieces together to achieve a spinner that will move for a while then stop.
float rotation = 1, stepSize = 10;
void setup() {
size(800, 800);
}
void draw() {
background(255);
strokeWeight(2);
fill(255, 0, 0);
rect(100, 100, 300, 300);
fill(0, 96, 255);
rect(100, 400, 300, 300);
fill(255, 240, 0);
rect(400, 100, 300, 300);
fill(0, 255, 0);
rect(400, 400, 300, 300);
strokeWeight(20);
pushMatrix();
translate(400, 400);
rotate(radians(rotation));
line(0, 0, 100, 100);
popMatrix();
if (stepSize > 0) {
rotation += stepSize;
stepSize -= 0.05; // play around with this value
}
}
void mousePressed() {
stepSize = random(5,15); // try adjusting these values
}
Very simple thing I'm trying to do here. I would like to have 2 images on top of one another. When i use my mouse event dragged and clicked on the top image, the area of the top level image selected will fade and make the lower image visible.
The way I see it, there are 2 ways I can do this:
I can make the top image Transparent over time (within the selected area)
or
I can delete the pixels individually in a spray can style fashion. Think the spray can tool from MS paint back in the day.
Heres some very basic code that i started which just lays the images on top of eachother
PImage sand;
PImage fossil;
void setup()
{
size(400,400);
background(255,255,0);
frameRate(30);
fossil = loadImage("foss.jpg");
sand = loadImage("sand.jpeg");
}
void draw()
{
image(fossil, 0, 0, width,height);
image(sand, 0, 0, width,height);
smooth();
if (mousePressed) {
fill(0);
tint(255,127); //the opacity function
} else {
fill(255);
}
}
So has anyone any comments on these 2 ways of creating opacity or perhaps there an easier way I've overlooked?
Perhaps I wasn't clear in my Spec as the 2 comments below are asking for clarification.
In its simplest terms, I have 2 images on top of each other. I would like to be able to make some modification to the top level image which would make the bottom image visible. However I need to make this modification to only part of the top level image.
I would like to know which is the better option. To make part of the top image become transparent using tint() or to delete the pixels from the top layer.
Then I will proceed with that approach. Any indication as to how to do it is also appreciated.
I hope this clears up any confusion.
If you simply want to crossfade between images, it can be with tint() as you code suggest. You were in fact quite close:
PImage sand;
PImage fossil;
void setup()
{
size(400, 400);
fossil = loadImage("CellNoise.jpg");
sand = loadImage("CellVoronoi.jpg");
}
void draw()
{
//tint from 255 to 0 for the top image
tint(255,map(mouseX,0,width,255,0));
image(fossil, 0, 0, width, height);
//tint from 0 to 255 for the bottom image - 'cross fade'
tint(255,map(mouseX,0,width,0,255));
image(sand, 0, 0, width, height);
}
For the "spray can style " erosion you can simply copy pixels from a source image into the destination image. It's up to you how you loop through pixels (how many, what order, etc.) to get the "spray" like effect you want, but here's a basic example of how to use the copy() function:
PImage sand,fossil;
int side = 40;//size of square 'brush'
void setup()
{
size(400, 400);
fossil = loadImage("CellNoise.jpg");
sand = loadImage("CellVoronoi.jpg");
}
void draw()
{
image(fossil, 0, 0, 400, 400);
if(mousePressed) {
for(int y = 0 ; y < side ; y++){
for(int x = 0; x < side; x++){
//copy pixel from 'bottom' image to the top one
//map sketch dimensions to sand/fossil an dimensions to copy from/to right coords
int srcX = (int)map(mouseX+x,0,width+side,0,sand.width);
int srcY = (int)map(mouseY+y,0,height+side,0,sand.height);
int dstX = (int)map(mouseX+x,0,width+side,0,fossil.width);
int dstY = (int)map(mouseY+y,0,height+side,0,fossil.height);
fossil.set(dstX, dstY, sand.get(srcX,srcY));
}
}
}
}
Note what I am simply looping to copy a square (40x40 in my case), but you can find other fun ways to loop and get different effects.
Have fun!