We are about to switch to a new forum software. Until then we have removed the registration on this forum.
panning generally means where in the stereo image the sound is. -1 for far left, +1 for far right.
Not much experience here:
With panning, you mean advancing/jumping in your sound track?
Kf
@kafrager thanks for anwering me !
Both of your solutions work. The first one even works with .wav files that I was using.
Now im having another problem that technically is out of the scope of this thread, but is related.
The objetive of my program is to record the panning and movement of sounds that I placed.
Here is an image showing the problem:
Here i´ve uploaded the code of the program : https://github.com/Aurelian24/espacializacion
The problem is that if I use the "Sampler" class or " FilePlayer " class i can´t accoplish panning or turning up and down the gain .
Hi @FRV!
Here is an example that displays two plots in two separate windows. I hope it helps you!
/*
Based on
https://gist.github.com/atduskgreg/666e46c8408e2a33b09a
https://forum.processing.org/two/discussion/12319/using-papplet-runsketch-to-create-multiple-windows-in-a-ps3-sketch
*/
import grafica.*;
GPlot plot1;
GPlot plot2;
void settings() {
size(450, 300);
}
void setup() {
// Start a new Processing applet
MyPApplet newApplet = new MyPApplet();
String[] args = {newApplet.getClass().getSimpleName()};
PApplet.runSketch(args, newApplet);
// Prepare the points for the first plot
int nPoints = 100;
GPointsArray points = new GPointsArray(nPoints);
for (int i = 0; i < nPoints; i++) {
points.add(i, 10*noise(0.1*i));
}
// Create the first plot
plot1 = new GPlot(this);
// Set the plot title and the axis labels
plot1.setTitleText("Plot 1 in main Processing applet");
plot1.getXAxis().setAxisLabelText("x axis");
plot1.getYAxis().setAxisLabelText("y axis");
// Add the points
plot1.setPoints(points);
// Activate the zooming and panning
plot1.activateZooming();
plot1.activatePanning();
}
void draw() {
// Draw the first plot
background(255);
plot1.defaultDraw();
}
public class MyPApplet extends PApplet {
public void settings() {
size(450, 300);
}
public void setup() {
// Prepare the points for the second plot
int nPoints = 100;
GPointsArray points = new GPointsArray(nPoints);
for (int i = 0; i < nPoints; i++) {
points.add(i, 10*noise(0.1*i));
}
// Create the second plot ("this" reffers to the newApplet instance)
plot2 = new GPlot(this);
// Set the plot title and the axis labels
plot2.setTitleText("Plot 2 in newApplet");
plot2.getXAxis().setAxisLabelText("x axis");
plot2.getYAxis().setAxisLabelText("y axis");
// Add the points
plot2.setPoints(points);
// Activate the zooming and panning
plot2.activateZooming();
plot2.activatePanning();
}
public void draw() {
// Draw the second plot
background(255);
plot2.defaultDraw();
}
}
Check previous posts as this has been addressed before:
https://forum.processing.org/two/search?Search=panning
Kf
https://forum.processing.org/two/discussion/comment/86915#Comment_86915
https://forum.processing.org/two/discussion/comment/85620/#Comment_85620
Other keyword to use in the forum: Panning
Kf
koogs can you confirm that panning, tilting and rolling the camera is all about applying transformations to the UP vector
No, just rolling is, and that's all you mentioned in the original question. (Chrisir, please note)
Panning a camera would involve moving the camera position and the look at by equal amounts.
But a plane is more about roll, pitch and yaw... Using gamestudio jargon is probably a bad idea given that you aren't using gamestudio, it'll just confuse people.
Thanks for you answers, I think I can formulate what I want to do in a simpler and better way :
1) I want to simulate a simplified plane flight - Me being inside the plane, pilot view
2) As shown here I need pan, tilt, roll : http://www.conitec.net/beta/aentity-pan.htm
3) koogs can you confirm that panning, tilting and rolling the camera is all about applying transformations to the UP vector ?
3) BUT what confuse me is that I don't want only to pan, tilt and roll the camera but also the trajectory of the plane. I mean if I only tilt I would "see" more sky but the trajectory of the plane will be still at the same altitude - I want to still look straight in front of me but having the plane going up on the slope.
4) The movements of the plane must combine, it could roll and tilt and turn left or right at the same time.
5) So, is it a UP vector AND velocity vector update question ?
6) If yes, what are the easier solutions to apply these transformations ? I know nothing about quaternions and transformation matrices. Any library I could use ? I search the Internet for hours but found no code to borrow, or that I could understand
7) Should I watch again and again https://youtube.com/watch?v=qMq-zd6hguc ? Is the answer there ? Applying angular motion on every axis ?
All of this is not for coding a realistic plane simulation but only small sequences of fake flights over landscapes, or in space that will be put together later in a video editing software (there is not graphic representation of the cookpit - the camera is at the nose of the plane)
My life would be easier if I wasn't so bad at maths ;-)
Here is a simplified version using a static XML file rather than a stream. The text from the xml file is posted directly below the code.
As a stop gap, have mapped the coordinates to roughly the correct locations. But once you zoom in/out, this mapping does not correspond.
Anyone with any tips on how to get this to work with 'Simplepointmarkers' or other wise where the coordinates are preserved regardless of panning/zooming would be much appreciated. Thank you :)
import de.fhpotsdam.unfolding.*;
import de.fhpotsdam.unfolding.geo.*;
import de.fhpotsdam.unfolding.utils.*;
import de.fhpotsdam.unfolding.marker.*;
UnfoldingMap map;
DebugDisplay debugDisplay;
Train_Class[] trains = new Train_Class[10];
XML xml; // A Table object
void setup() {
size(1024, 768, P2D);
map = new UnfoldingMap(this, "myMap");
map.zoomAndPanTo(new Location(53.0980f, -7.9097f), 7);
MapUtils.createDefaultEventDispatcher(this, map);
debugDisplay = new DebugDisplay(this, map);
for (int i = 0; i < 10; i++) {
trains[i] = new Train_Class(width/2, height/2, random(100));
}
}
void draw() {
map.draw();
debugDisplay.draw();
xml = loadXML("xml.xml"); // Load XML file
XML[] children = xml.getChildren("objTrainPositions"); // Get all the child nodes named "objTrainPositions"
for (int i = 0; i < 10; i++) {
XML trainCodeElement = children[i].getChild("TrainCode");
String trainCode = trainCodeElement.getContent();
XML latitudeElement = children[i].getChild("TrainLatitude");
float latitude = latitudeElement.getFloatContent();
XML longitudeElement = children[i].getChild("TrainLongitude");
float longitude = longitudeElement.getFloatContent();
println("Train Code: " + trainCode + ", Latitude: " + latitude + ", Longitude: " + longitude);
float mappedLatitude = map(latitude, 55.557, 50.497, 0, height);
float mappedLongitude = map(longitude, -13.535, -2.296, 0, width);
trains[i].display(mappedLongitude, mappedLatitude);
}
}
class Train_Class {
float x, y;
float colour;
// Create the Train
Train_Class (float x_, float y_, float colour_) {
x = x_;
x = y_;
colour = colour_;
}
void display(float posX, float posY) { // Display the Train
x = posX;
y = posY;
fill(colour);
stroke(255,0,0);
ellipse(x, y, 4, 4);
}
}
<ArrayOfObjTrainPositions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://api.irishrail.ie/realtime/">
<objTrainPositions>
<TrainStatus>N</TrainStatus>
<TrainLatitude>53.1442</TrainLatitude>
<TrainLongitude>-6.06085</TrainLongitude>
<TrainCode>E917</TrainCode>
<TrainDate>02 Apr 2018</TrainDate>
<PublicMessage>...</PublicMessage>
<Direction>Northbound</Direction>
</objTrainPositions>
<objTrainPositions>
<TrainStatus>R</TrainStatus>
<TrainLatitude>53.2557</TrainLatitude>
<TrainLongitude>-6.11317</TrainLongitude>
<TrainCode>E214</TrainCode>
<TrainDate>02 Apr 2018</TrainDate>
<PublicMessage>...</PublicMessage>
<Direction>Southbound</Direction>
</objTrainPositions>
<objTrainPositions>
<TrainStatus>R</TrainStatus>
<TrainLatitude>53.2756</TrainLatitude>
<TrainLongitude>-6.10333</TrainLongitude>
<TrainCode>E916</TrainCode>
<TrainDate>02 Apr 2018</TrainDate>
<PublicMessage>...</PublicMessage>
<Direction>Northbound</Direction>
</objTrainPositions>
<objTrainPositions>
<TrainStatus>R</TrainStatus>
<TrainLatitude>53.2991</TrainLatitude>
<TrainLongitude>-6.16512</TrainLongitude>
<TrainCode>E108</TrainCode>
<TrainDate>02 Apr 2018</TrainDate>
<PublicMessage>...</PublicMessage>
<Direction>Southbound</Direction>
</objTrainPositions>
<objTrainPositions>
<TrainStatus>R</TrainStatus>
<TrainLatitude>53.3206</TrainLatitude>
<TrainLongitude>-6.21112</TrainLongitude>
<TrainCode>E808</TrainCode>
<TrainDate>02 Apr 2018</TrainDate>
<PublicMessage>
E808\n17:10 - Greystones to Malahide (1 mins late)\nArrived Sydney Parade next stop Sandymount
</PublicMessage>
<Direction>Northbound</Direction>
</objTrainPositions>
<objTrainPositions>
<TrainStatus>R</TrainStatus>
<TrainLatitude>53.3531</TrainLatitude>
<TrainLongitude>-6.24591</TrainLongitude>
<TrainCode>E215</TrainCode>
<TrainDate>02 Apr 2018</TrainDate>
<PublicMessage>
E215\n17:30 - Howth to Bray (-3 mins late)\nArrived Dublin Connolly next stop Tara Street
</PublicMessage>
<Direction>Southbound</Direction>
</objTrainPositions>
<objTrainPositions>
<TrainStatus>R</TrainStatus>
<TrainLatitude>53.3629</TrainLatitude>
<TrainLongitude>-6.22753</TrainLongitude>
<TrainCode>E915</TrainCode>
<TrainDate>02 Apr 2018</TrainDate>
<PublicMessage>
E915\n17:00 - Bray to Howth (3 mins late)\nDeparted Clontarf Road next stop Killester
</PublicMessage>
<Direction>Northbound</Direction>
</objTrainPositions>
<objTrainPositions>
<TrainStatus>R</TrainStatus>
<TrainLatitude>53.392</TrainLatitude>
<TrainLongitude>-6.11448</TrainLongitude>
<TrainCode>E216</TrainCode>
<TrainDate>02 Apr 2018</TrainDate>
<PublicMessage>
E216\n17:45 - Howth to Bray (1 mins late)\nDeparted Sutton next stop Bayside
</PublicMessage>
<Direction>Southbound</Direction>
</objTrainPositions>
<objTrainPositions>
<TrainStatus>T</TrainStatus>
<TrainLatitude>53.1442</TrainLatitude>
<TrainLongitude>-6.06085</TrainLongitude>
<TrainCode>E107</TrainCode>
<TrainDate>02 Apr 2018</TrainDate>
<PublicMessage>
E107\n16:27 - Howth to Greystones(2 mins late)\nTERMINATED Greystones at 17:47
</PublicMessage>
<Direction>Southbound</Direction>
</objTrainPositions>
<objTrainPositions>
<TrainStatus>T</TrainStatus>
<TrainLatitude>53.4509</TrainLatitude>
<TrainLongitude>-6.15649</TrainLongitude>
<TrainCode>E807</TrainCode>
<TrainDate>02 Apr 2018</TrainDate>
<PublicMessage>
E807\n16:43 - Bray to Malahide(0 mins late)\nTERMINATED Malahide at 17:50
</PublicMessage>
<Direction>Northbound</Direction>
</objTrainPositions>
</ArrayOfObjTrainPositions>
While writing the main post, I realized that you should rotate the camera in the opposite direction. Not only does it work just as well, it makes it easier to rotate multiple objects, and enables panning and zooming.
Hi again.
I have worked a bit further on my inital patch by adding an array of swimming fish and some OSC connectivity for audio visual reactions. After some effort, OSC panning and other effects I added seem to work. Each orb now vibrates to it’s own separate audio loop playing from a MAX Msp patch.
I have been attempting two things with the array of fish; #1 to vibrate and #2 change their color when either or both orbs plunge beneath the water. Again I seem to have hit a wall here. The fish only react to one orb, but not both at once. I can chose which orb by referring to its index number. I figured this should be pretty simple, according to everything else I have working similarly. I have tried the method that BGADII suggested with my first query, and several others, but to no avail.
The array for the two orbs is proving problematic. It might seem a bit overkill, but the reason for that array is that I will eventually add many more orbs(sound sources). The script overall is becoming quite confusing. I have pulled it apart several times to solve issues.
I'd be really grateful if anyone would share some tips on my fish issue... and also general ways to clean up this sketch?
I have been looking at the native object/class examples in the processing examples folder, but I'm not sure what methods work best for classes with values that interconnect. I am worried that if the patch gets any bigger it'll become wildly confusing (to me;).
Many thanks!
import ddf.minim.*;
Minim minim;
AudioPlayer[] popsound;
import oscP5.*;
import netP5.*;
OscP5 oscP5;
NetAddress myRemoteLocation; // ************************************
int numberOfOrbs = 2;
float[] incomingKickOSC = new float[numberOfOrbs]; // declare OSC message variable
Orb_Class[] many_Orbs = new Orb_Class[numberOfOrbs];
ArrayList<Bubble_Class> many_Bubbles = new ArrayList();
Fish_Class[] many_Fish = new Fish_Class[30];
// Constant Environmental Variables
float spaceHeight;
float waterSurfaceHeight;
float seaFloor;
float orbFishProximityBounces = 0;
float orbSpaceProximityBounces = 0;
//Fish Parameters
float fishColor = 0;
float fishHeight;
float radius;
// ------------------------------------------------------------------------------------------------ SETUP
void setup() {
size(1000, 800, P3D);
noStroke();
smooth();
oscP5 = new OscP5(this,11100); // start oscP5, listening for incoming messages at port 11000
myRemoteLocation = new NetAddress("127.0.0.1",11000); // SEND OSC messages to Max MSP
spaceHeight = (height/3);
waterSurfaceHeight = (height/3)*2;
seaFloor = height;
fishHeight = ((height/6)*5);
popsound = new AudioPlayer[numberOfOrbs]; // ************************************
minim = new Minim(this);
for (int i=0; i<many_Orbs.length; i++) {
many_Orbs[i] = new Orb_Class(64, random(4, 6), random(2, 4));
popsound[i] = minim.loadFile("splash.mp3");
}//for
for (int i=0; i<many_Fish.length; i++) {
many_Fish[i] = new Fish_Class(0, random(waterSurfaceHeight, seaFloor), random(1, 3));
}//for
}//setup
// ------------------------------------------------------------------------------------------------ DRAW
void draw() {
background( 0, 0, 255 ); // erase the window to black
lights();
line(0, waterSurfaceHeight, width, waterSurfaceHeight);
for (int j=0; j<many_Orbs.length; j++) { // display red orbs
many_Orbs[j].display(j);
many_Orbs[j].move(j);
many_Orbs[j].fishBounceAndColoredOrNot();
many_Orbs[j].skyReverberatesSound();
many_Orbs[j].underwaterFiltersSound();
many_Orbs[j].panSoundsInMax();
}//for
for (int i=0; i<many_Fish.length; i++) {
many_Fish[i].moveFish();
many_Fish[i].displayFish();
}//for
for (Bubble_Class b : many_Bubbles) { // move through ArrayList
b.ascend();
b.burstAtSurface();
b.display();
}//for
for (int i=many_Bubbles.size()-1; i>=0; i--) { // to remove we must move backwards through the ArrayList
Bubble_Class b = many_Bubbles.get(i);
//popsound[i] = minim.loadFile("pop.mp3");
if (b.isDead){
many_Bubbles.remove(i);
}//if
}//for
tint(255, 127); // Display at half opacity
fill(0, 41, 158, 200);
noStroke();
rect(0, height-height/3, width, height/3); // The Ocean
// ---------------------- SENDING OSC MESSAGES TO MAX MSP ----------------------------------------
OscMessage myMessage = new OscMessage("/oscFromProcToMax");
myMessage.add(many_Orbs[0].mappedFreq);
myMessage.add(many_Orbs[1].mappedFreq);
myMessage.add(many_Orbs[0].mappedVerbLevel); /// *****************!!!!!!!!!
myMessage.add(many_Orbs[1].mappedVerbLevel);
myMessage.add(many_Orbs[0].panningLeftRight);
myMessage.add(many_Orbs[1].panningLeftRight);
oscP5.send(myMessage, myRemoteLocation); /* send the message */
}//Draw
// ---------------------- RECEIVING OSC MESSAGES FROM MAX ----------------------------------------
// Technique found at: http://www.technopagan.net/blog/tech/processing-osc/
void oscEvent(OscMessage theOscMessage1) {
if (theOscMessage1.addrPattern().equals("/oscAmp")) {
if(theOscMessage1.checkTypetag("ff") == true){
//println(theOscMessage1.typetag());
for(int i=0; i < numberOfOrbs; i++) {
incomingKickOSC[i] = theOscMessage1.get(i).floatValue();
}//for
}//if
}//if
}//draw
// -------------------------------------------------------------------------------------------------- ORB CLASS
class Orb_Class {
float mappedFreq; //OSC variables
float mappedVerbLevel; //OSC variables
float panningLeftRight; //OSC variables
float orbx;
float orby = random(300, height-100); // location
float xspeed, yspeed; // speed
float xtime;
float ytime;
int timer;
int duration= int(random(900, 1600));
// Constructor
Orb_Class(float tempR, float tempXt, float tempYt) {
radius = tempR;
xspeed = tempXt;
if (random(100)<50){
xspeed *= -1;
}//if
yspeed = tempYt;
if (random(100)<50){
yspeed *= -1;
}//if
}
void move(int arrayIndex){
orbx += xspeed; // Increment x
orby += yspeed; // Increment y
if (orbx > width || orbx < 0) { // Check horizontal edges
xspeed *= -1;
}//if
if (orby > height || orby < 0) { // Check vertical edges
yspeed *= -1;
}//if
if (orby > height/2){
if (millis() - timer >= duration) {
int upperBound = int(random(30));
for (int i=0; i<upperBound; i++) {
many_Bubbles.add( new Bubble_Class(orbx, orby, 10, 1) );
}//for
timer = millis();
duration=int(random(100, 300));
}//if
}//if
if (orby+radius <= waterSurfaceHeight){ //Splash sound as orbs breach surface
popsound[arrayIndex].rewind();
popsound[arrayIndex].play();
}//if
}//void move
void display(int arrayIndex){
pushMatrix();
translate(orbx, orby, 0);
fill(255, 0, 0);
noStroke();
sphere(radius/2+(incomingKickOSC[arrayIndex]*200));
popMatrix();
}
void panSoundsInMax(){
panningLeftRight = map(orbx, 0, width, 0.2, 0.8);
}
void fishBounceAndColoredOrNot(){
if ( ( orby > (waterSurfaceHeight+radius/2) ) ){
fishColor = 255;
orbFishProximityBounces = 1;
}//if
else{
fishColor = 0;
orbFishProximityBounces = 0.01;
}//else
}
void underwaterFiltersSound(){
if ( (orby < (waterSurfaceHeight+radius/2)) && (orby > (waterSurfaceHeight-radius/2)) ) {
mappedFreq = map(orby, (waterSurfaceHeight+(radius/2)), (waterSurfaceHeight-(radius/2)), 0, 20000);
}//if
}
void skyReverberatesSound(){
if ( (orby > (spaceHeight-radius/2)) && (orby < (spaceHeight+radius/2)) ) {
mappedVerbLevel = map(orby, (spaceHeight-(radius/2)), (spaceHeight+(radius/2)), 0, -72.6);
//orbSpaceProximityBounces = map(orby, (spaceHeight-(radius/2)), (spaceHeight+(radius/2)), 1, 0);
}//if
}
}
// -------------------------------------------------------------------------------------------------- BUBBLE CLASS
class Bubble_Class {
float diameter;
float riseSpeed;
float bubblex, bubbley;
color color1;
boolean isDead=false;
Bubble_Class(float tempX, float tempY, float tempD, float tempRs) {
bubblex = tempX+random(-12, 12);
bubbley = tempY+random(-12, 12);
diameter = tempD;
riseSpeed = tempRs + random(1, 3);
color1=color(random(127, 256), random(70, 256));
}
void ascend() {
bubbley = bubbley - riseSpeed;
if (bubbley<-30){
isDead=true;
}//if
}
void burstAtSurface() { // Burst the bubbles as they reach the surface
if (bubbley < ((height/3)*2)+diameter) {
isDead=true;
}//if
}
void display() {
fill(color1);
ellipse(bubblex, bubbley, diameter, diameter);
}
}
// -------------------------------------------------------------------------------------------------- FISH CLASS
class Fish_Class
{
float fishx;
float fishHeightConstrained;
float fishSpeed;
float fishy;
// Constructor
Fish_Class(float tempXpos, float tempYpos, float tempSpeed) {
fishx = tempXpos;
fishSpeed = tempSpeed;
fishy = tempYpos;
}
void moveFish() {
fishx = fishx + fishSpeed;
for (int i=0; i<numberOfOrbs; i++) {
fishy = fishy + (random(-10,10)*(incomingKickOSC[i]*5*orbFishProximityBounces) ); /// *****************!!!!!!!!!
}//for
fishHeightConstrained = constrain(fishy, 900, 600);// + (random(-10,10)*orbProximityToFish);
if (fishx > width) {
fishx = 0;
}//if
if (fishy < waterSurfaceHeight) {
fishy = 900;
}//if
}//moveFish
void displayFish() {
fill(fishColor);
triangle(fishx, fishy, fishx-20, fishy+8, fishx-20, fishy-5);
ellipse(fishx, fishy, random(20, 30), random(10, 15)) ;
}
}
//
Hello. Thank you for your valuable help. what I'd like to do is draw the graph and at the same time fill in the table with each mouse pressed. When I press the "z" key, start drawing the graph again (without deleting the first track) and compiling a new table. Or save the file of the first graph and its table, to recall only the graph line and the table and make it appear on a new sketch. Being a young novice kid with processing all your help for me is very welcome. Thank you!!!
import processing.serial.*;
import controlP5.*; // import controlP5 library
import grafica.*;
ControlP5 controlP5; // controlP5 object
ArrayList<PVector> punto = new ArrayList();
Serial myPort; // The serial port:
PFont f; // The display font:
String inString; // Input string from serial port:
int lf = 10; // ASCII linefeed
float deg, val;
int myColorBackground = color(0,0,0);
Knob myKnob1,myKnob2,myKnob3,myKnob4;
int i;
int y;
int knobValue = 100;
int xPos=0;
GPlot plot1, plot2;
int a=1;
int x=0;
void setup() {
size(1350,750);
PFont f= loadFont ("AgencyFB-Bold-25.vlw");
textFont(f);
myPort = new Serial(this, "com3", 9600);
myPort.bufferUntil(lf);
{
smooth(); //ControlP5
controlP5 = new ControlP5(this); //ControlP5
myKnob1 = controlP5.addKnob("1")
.setRange(0,5)
.setValue(0)
.setPosition(700,10)//posizione 605
.setTickMarkLength(10)
.setColorForeground(color(#FF0004))//colore cursore
.setColorBackground(color(255))//colore sfondo
.setColorValueLabel(color(0))//colore numeri//label etichetta
.setColorActive(color(#6AFA05))
.setDragDirection(Knob.VERTICAL)
.lock()
.setSize(150,150)//dimensioni
. setDecimalPrecision(2) //numero dopo la virgola
;
myKnob1 .getCaptionLabel()
. setFont(f);
myKnob1.getValueLabel()
.setFont(f)
;
myKnob2 = controlP5.addKnob("2")
.setRange(0,500)
.setValue(0)
.setPosition(900,10)
.setColorForeground(color(#FF0004))//colore cursore
.setColorBackground(color(255))//colore sfondo
.setColorValueLabel(color(0))//colore numeri//label etichetta
.setColorActive(color(#6AFA05))
.setDragDirection(Knob.VERTICAL)
.lock()
.setSize(150,150)//dimensioni
.setDecimalPrecision(2) //numero dopo la virgola
.setTickMarkLength(10)
;
myKnob2 .getCaptionLabel()
. setFont(f);
myKnob2.getValueLabel()
.setFont(f)
;
myKnob3 = controlP5.addKnob("3")
.setRange(0,500)
.setValue(1)
.setPosition(1100,10)
.setColorForeground(color(#FF0004))//colore cursore
.setColorBackground(color(255))//colore sfondo
.setColorValueLabel(color(0))//colore numeri//label etichetta
.setColorActive(color(#6AFA05))
.setDragDirection(Knob.VERTICAL)
.lock()
.setSize(150,150)//dimensioni
.setDecimalPrecision(2) //numero dopo la virgola
.setTickMarkLength(10)
;
myKnob3 .getCaptionLabel()
. setFont(f);
myKnob3.getValueLabel()
.setFont(f)
;
plot1 = new GPlot(this);
plot1.setPos(200,200);//posizione
plot1.setMar(0, 100, 0,100);
plot1.setDim(1000, 480);//dimensione
plot1.setAxesOffset(4);
plot1.setTicksLength(4);
// Create the second plot with the same dimensions
plot2 = new GPlot(this);
// Prepare the points Prepara i punti
int myKnob1 =0;
GPointsArray points = new GPointsArray(myKnob1);
for (int i = 0; i < 13; i++) {
if(xPos==13){
}
}
plot1.setPoints(points);
plot1.getYAxis().setAxisLabelText("MASSA ARIA (?)");
plot1.getXAxis().setAxisLabelText("APERTURA VALVOLA (mm)");
// Attiva il panning (solo per il primo grafico)
plot1.activatePanning();
}
}
void serialEvent(Serial p) {
inString = p.readString();
char primo=inString.charAt(0); // primo carattere
String cifra=inString.substring(1); // da secondo carattere in poi
float val=parseFloat(cifra); // valore da 0-255 o 0-1023, non sò cosa spedisce arduino
print("val="); println(val);
inString = trim(inString);
// // converte in int e mappa all'altezza dello schermo:
switch(primo) {
case ('A'): myKnob1.setValue(val);
break;
case ('B'): myKnob2.setValue(val);
break;
case ('C'): myKnob3.setValue(val);
break;
}
}
void draw() {
background(255);
fill(0);
rect(680,6,600,180,10);
// fill(0);
rect(380,105,200,50,10);
// show data
rect(55,350,118,25,10);
rect(55,380,30,325,10);
int y=400;//asse y
for (PVector myKnob1 : punto) {
{
fill(255);
textSize(22);
textSize(18);
text("0",60,400);
text("1",60,420);
text("2",60,440);
text("3",60,460);
text("4",60,480);
text("5",60,500);
text("6",60,520);
text("7",60,540);
text("8",60,560);
text("9",60,580);
text("10",60,600);
text("11",60,620);
text("12",60,640);
text("13",60,660);
text("14",60,680);
text("15",60,700);
}
fill(0);
text(+myKnob1.y, 90, y);
y+=20; //next line
}
{
//Disegna la prima trama
plot1.beginDraw();
plot1.drawBox();
plot1.drawXAxis();
plot1.drawYAxis();
plot1.drawTitle();
plot1.drawGridLines(GPlot.BOTH);
plot1.drawLines();
plot1.endDraw();
textSize(25);
fill(255);
text(( myKnob2.getValue()- myKnob3.getValue()),400,140);
}
{
textSize(50);
fill(0);
}
}
void mousePressed(){
GPoint lastPoint = plot2.getPointsRef().getLastPoint();
if (lastPoint == null) {
plot1.addPoint(xPos, +myKnob1.getValue(), "(" + str(xPos) + " , " + str(myKnob1.getValue()) + ")");
}
else if (!lastPoint.isValid() || sq(lastPoint.getX() - xPos) + sq(lastPoint.getY() + myKnob1.getValue()) > 2500) {
}
// Reset the points if the user pressed the space bar
if (keyPressed && key == ' ') {
plot1.setPoints(new GPointsArray());
}
if( mouseButton == LEFT ) xPos+=1;
{
punto.add(new PVector(i, myKnob1.getValue()));
a++;
}
}
Is there a value you can pass to pan() that makes it an identity operator, the same way multiplying by 1 doesn't change the input?
"A pan value of -1 pans completely to the left, 1 pans completely to the right, and 0 results in center panning. "
So, 0 then...
Hello everyone! It's my first post so please forgive any issues. I've been using Processing for some time now but I'd still consider myself as a beginner! I'm studying Popular Music and together with friends we want to create an interactive installation for a uni project, it would be a massive massive help from you to tell us if what we want to do is possible. The idea is to make an interactive audio-visual installation using Kinect. The installation where a person acts as an instrument. We're thinking of using Kinect to detect colours, depth and movement, that would ideally trigger certain parameters in sounds. For example: bright colours = higher frequencies, body movement from left to right = panning, etc. We would be super thankful if you could give us a bit of help or advice! All the best, Marta
If you remove your scale() function call - line 27, everything works fine. If you execute your sketch scaled, you will see that your drawing buffer is scaled but your mouse pointer doesn't know about this change. This is because Processing doesn't scale your mouse pointer. You have to do it yourself.
So below is an example implementing some changes in your code. In a nutshell, you need to use mX
and mY
instead of mouseX
and mouseY
. An alternative is to use the Mouse2DTransformations library. You can install it through the Processing PDE and then check the provided examples. A final alternative is to check previous posts related to panning.
https://forum.processing.org/two/discussion/1364/constraining-an-image-while-panning-and-zooming
https://forum.processing.org/two/discussion/20853/scale-translate-ab-comparission#latest
https://forum.processing.org/two/discussion/20813/zooming-and-panning-headache#latest
Kf
final float scaleFactor=0.7;
float mX;
float mY;
int rectX, rectY; // Position of square button
int circleX, circleY; // Position of circle button
int rectSize = 90; // Diameter of rect
int circleSize = 93; // Diameter of circle
color rectColor, circleColor, baseColor;
color rectHighlight, circleHighlight;
color currentColor;
boolean rectOver = false;
boolean circleOver = false;
void setup() {
//fullScreen();
size(500, 500);
ellipseMode(CENTER);
rectColor = color(0);
rectHighlight = color(51);
circleColor = color(255);
circleHighlight = color(204);
baseColor = color(102);
currentColor = baseColor;
circleX = width/2+circleSize/2+10;
circleY = height/2;
rectX = width/2-rectSize-10;
rectY = height/2-rectSize/2;
}
void draw() {
background(currentColor);
fill(0, 255, 0);
ellipse(mouseX, mouseY, 50, 50);
text("mouseX, mouseY B4", mouseX+50, mouseY);
scale(scaleFactor); // <----- I scaled here
mX=mouseX/scaleFactor;
mY=mouseY/scaleFactor;
fill(255, 0, 0);
ellipse(0, 0, 50, 50);
fill(255, 0, 0);
ellipse(mX, mY, 50, 50);
text("mx,my", mX+50, mY);
fill(255, 255, 0);
ellipse(mouseX, mouseY, 5, 5);
text("mouseX, mouseY after", mouseX+50, mouseY);
update(mX, mY);
if (rectOver) {
fill(rectHighlight);
} else {
fill(rectColor);
}
stroke(255);
rect(rectX, rectY, rectSize, rectSize);
if (circleOver) {
fill(circleHighlight);
} else {
fill(circleColor);
}
stroke(0);
ellipse(circleX, circleY, circleSize, circleSize);
}
void update(float x, float y) {
if ( overCircle(circleX, circleY, circleSize) ) {
circleOver = true;
rectOver = false;
} else if ( overRect(rectX, rectY, rectSize, rectSize) ) {
rectOver = true;
circleOver = false;
} else {
circleOver = rectOver = false;
}
}
void mousePressed() {
if (circleOver) {
currentColor = circleColor;
} else if (rectOver) {
currentColor = rectColor;
} else
currentColor=baseColor;
}
boolean overRect(int x, int y, int width, int height) {
if (mX >= x && mX <= x+width &&
mY >= y && mY <= y+height) {
return true;
} else {
return false;
}
}
boolean overCircle(float x, float y, int diameter) {
float disX = x - mX;
float disY = y - mY;
if (sqrt(sq(disX) + sq(disY)) < diameter/2 ) {
return true;
} else {
return false;
}
}
If you just want to use your monitor as a shrunk preview (without panning around on a larger surface) then one approach is:
PGraphics pg
pg
image(pg, 0, 0, 1600, 1600)
This will fit the image on your monitor. To center, translate by 480. pg
to disk.This scaling is expensive, so if you don't want the preview to consume too many resources during drawing you could decide to only refresh the preview every %n frames, e.g. once a second -- it really depends on what your preview needs and hardware resources are.
One generic fit algorithm for shrinking any large image to any screen dimensions is to find the ratios of your canvas w/h to image w/h, then scale both sides of your image to whichever is the smaller ratio.
wratio = width/pg.width;
hratio = height/pg.height;
scale = min(wratio/hratio);
image(pg, 0, 0, pg.width*scale, pg.height*scale);
You need to implement your own zoom functions. Explore similar topics at:
https://forum.processing.org/two/search?Search=panning
Kf
get() will get you the current PImage of the associated PGraphics. The main sketch is a PGraphics itself. Calling get()
by itself gives you a copy of the current drawing buffer. If you are using another buffer, as for example:
PGraphics secondBuffer=createGraphics(width*2,height,JAVA2D);
then secondBuffer.get()
will return a copy of this buffer. Notice this buffer is bigger than the current canvas.
I have not followed all these posts but I think what you could do is draw everything on a second buffer and then get() a section of that buffer. For instance:
secondBuffer.get(0,0,width/2,height/2);
Gets you one quarter of your image store in secondBuffer. As a matter of fact, there are previous post in the forum related to using bigger PGraphics than the current canvas. Use the keyword panning.
Kf
Thank you, but the interface in the video you see at the start is just Audacity! I'll have to clarify that in the post. I'm showing Audacity just to show how it sounds when it's pure mono and so you could see (and hear) panning only changing the volume. I am looking for a nice way of making an interface for animating the sounds in 3D, because right now I just move the sphere using the arrows keys. Glad to hear it'd be a fitting thing to be a library! :) Guess I really need to think harder how to make it more presentable so people would know exactly what's going on quickly.