How do I adjust Processing/Minim waveform scale? - java

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();
}

Related

Changing color of sphere with time (processing)

I am a new coder on processing, because of this reason please be gentle.
Normally my code is more longer and complex but I wrote a simple code for you, which I can adapt on my code:
int speed = 1;
int x, z = 50;
void setup() {
size(400, 400, P3D);
}
void draw() {
background(0);
noStroke();
lights();
translate(x, height/2, z);
fill(255,0,0);
sphere(25);
if (x > width -50)
noLoop();
x += speed;
}
So, like you see, sphere starts with color of red and it reaches end of the window. I want to change it's color from red to white and it should take 30 sec. to reach end of the window. However I don't know how. If you help me I will be happy.
Note: I tried lerpColor function but didn't help me.
Math is the secret. Is often is.
There are a couple things you'll need to keep track of to accomplish this: the time it takes to cross the screen (you said 30 seconds), the speed of the sphere, the speed at which the color changes.
Before we start, I suggest that you use float for your variables which are positions and speeds. Integers will do the job, but at some point when you want precision you may regret not using floats or a similar type.
There are 2 ways to deal with changes over time: you can calculate time and draw what needs to be drawn where it's supposed to be, or calculate how many frames will be drawn in a certain amount of time and move things accordingly. The first technique has the advantage of being able to draw things where they are supposed to be even if the system is laggy (Processing will lower the framerate if it's not able to respect it), while the second is often easier to work with. We'll go with the framerate technique, as this is not supposed to be complicated and because most programs won't need so much resource that it'll lower the framerate.
The framerate, in Processing, is also the rate at which the main loop (the draw() loop) run. So we'll choose a framerate which will let us calculate the speed of the sphere and the speed at which the color change. The rest is just watching it move.
Here's your example, but modified so it works approximately as you told:
float speed;
float x, z = 50;
float greenBlueStrength = 0;
float colorFadeRate = 1;
int fadeTimeInFrames;
void setup() {
size(400, 400, P3D);
frameRate(60); // 60 is the default framerate per second
// so 30 seconds == (30*60) == 1800 frames
// so you must have the speed to match
fadeTimeInFrames = 60 * 30;
speed = (width - 50) / (float)fadeTimeInFrames;
colorFadeRate = 255 / (float)fadeTimeInFrames;
println(colorFadeRate);
}
void draw() {
background(0);
textSize(30);
text((millis()/1000) + " s. // color: " + (int)greenBlueStrength, 20, 50);
// this is just to keep track of changes while they happen
noStroke();
lights();
translate(x, height/2, z);
fill(255, greenBlueStrength, greenBlueStrength);
sphere(25);
if (x > width -50) {
noLoop();
} // no actual change, but use brackets anyway, it's easier to read
// updating what needs to be updated
x += speed;
greenBlueStrength += colorFadeRate;
}
I'll hang around so don't hesitate if you have questions.
Have fun!
I think something like that would work:
int r=255,b=255,g=255;
...
void draw(){
...
int percent=x/width*100;
fill(r,b*percent,g*percent)
sphere(25)
...
}
so the sphere would be red only on the left of the screen and white on the right

How to zoom into mouse position with correct translation

I'm trying to zoom a grid in Processing and I am having trouble with applying the correct translation such that zooming is centered around the mouse position. I have searched the web for a while but nothing I try seems to work.
The screen size is width and height and the mouse position is mouseX and mouseY.
The code I have at the moment is below, but it zooms the grid (controlled by player.zoom) from the top left corner which is not what I want. To update the translation of the grid, player has the 2d vector player.translate.
void mouseWheel(MouseEvent event) {
float zoomFactor = 200.0f;
float scroll = event.getCount();
player.zoom -= scroll * player.zoom / zoomFactor;
// player.translate.x += something;
// player.translate.y += something;
}
If you need more details to answer I can link the repo with the source code.
I have created a very simple mock-up for you which will hopefully point you in the right direction into applying this to your player.
So this little demo shows the zooming in to the centre of an ellipse whilst keeping it as the central focus.
float scale = 1;
// displacement left/right
float xPan = 720;
// displacement up/down
float yPan = 450;
boolean zoomIn = true;
void setup() {
size(1440, 900);
}
void draw() {
// allows us to zoom into the center of the screen rather than the corner
translate(width/2, height/2);
scale(scale);
translate(-xPan, -yPan);
background(200);
// draws the ellipse in the center
ellipse(width/2, height/2, 100, 100);
// does the zooming
if (zoomIn) {
scale *= 1.01;
}
}
I suggest you to copy this into a new project and then comment out specific lines to try to understand what's going on and how you can transfer this over to your own project.
The same principles still apply, I didn't do this with mouse input in the effort of making the program as simple as possible.

(Processing)How to move a 3D object according to the screen's XY axis, instead of the world's X,Y,Z(PeasyCam)

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();
}

Java/Processing - imported objects disappear close to camera

I've imported an object into Processing that I created in Blender.
The code below works and the object appears but seemingly very small (or distant).
If I try to move close to the object with PeasyCamm it disappears completely before it gets close enough to see properly. The only thing I could figure is that the object itself is very close to the camera but is in fact tiny...
I attempted to scale the object but a call to
myshape.getVertexCount()
indicates my object has no vertices and nothing I do seems to change anything. I have a tiny rendered object that disappears at about a quarter of the screen height.
PShape myshape;
import peasy.test.*;
import peasy.org.apache.commons.math.*;
import peasy.*;
import peasy.org.apache.commons.math.geometry.*;
PeasyCam camera;
void setup(){
size( 640, 480, P3D);
camera = new PeasyCam(this, 0, 0, 0, 50);
frameRate(10);
myshape = loadShape("test.obj");
for (int i = 0; i < myshape.getVertexCount(); i++){
PVector v = myshape.getVertex(i);
println("Inside");
v.x *= 45;
v.y *= 45;
v.z *= 45;
myshape.setVertex(i, v);
}
}
void draw(){
background(0);
shape(myshape);
}
The getVertexCount() and getVertex() functions only work with shapes that you create in the code, using the vertex() function. More info can be found in the reference.
If all you want to do is scale your shape, then you can simply use the scale() function. Here is some example code that scaled your object by a factor of 20:
PShape myshape;
void setup() {
size(500, 500, P3D);
myshape = loadShape("test.obj");
}
void draw() {
background(0);
translate(width/2, height/2, 100);
scale(20);
shape(myshape);
}
Edit: Apparently you can still get to the vertexes inside an object file, it just isn't as straightforward as calling the getVertex() function. First you have to loop through the shape's children and then call getVertex() on the children. More info in this forum post (see jeremydouglass's answer).

Opacity in images with Processing

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!

Categories