moving examples to hang out with their libraries

This commit is contained in:
benfry
2011-01-26 19:43:04 +00:00
parent ce5fd461f5
commit a53f278863
81 changed files with 0 additions and 0 deletions
+42
View File
@@ -0,0 +1,42 @@
/**
* Add Listener
* by Damien Di Fede.
*
* This sketch demonstrates how to use the <code>addListener</code> method of a <code>Recordable</code> class.
* The class used here is <code>AudioPlayer</code>, but you can also add listeners to <code>AudioInput</code>,
* <code>AudioOutput</code>, and <code>AudioSample</code> objects. The class defined in waveform.pde implements
* the <code>AudioListener</code> interface and can therefore be added as a listener to <code>groove</code>.
*/
import ddf.minim.*;
Minim minim;
AudioPlayer groove;
WaveformRenderer waveform;
void setup()
{
size(512, 200, P2D);
minim = new Minim(this);
groove = minim.loadFile("groove.mp3", 512);
groove.loop();
waveform = new WaveformRenderer();
groove.addListener(waveform);
}
void draw()
{
background(0);
// see waveform.pde for an explanation of how this works
waveform.draw();
}
void stop()
{
// always close Minim audio classes when you are done with them
groove.close();
// always stop Minim before exiting.
minim.stop();
super.stop();
}
+76
View File
@@ -0,0 +1,76 @@
// This class is a very simple implementation of AudioListener. By implementing this interface,
// you can add instances of this class to any class in Minim that implements Recordable and receive
// buffers of samples in a callback fashion. In other words, every time that a Recordable object has
// a new buffer of samples, it will send a copy to all of its AudioListeners. You can add an instance of
// an AudioListener to a Recordable by using the addListener method of the Recordable. If you want to
// remove a listener that you previously added, you call the removeListener method of Recordable, passing
// the listener you want to remove.
//
// Although possible, it is not advised that you add the same listener to more than one Recordable.
// Your listener will be called any time any of the Recordables you've added it have new samples. This
// means that the stream of samples the listener sees will likely be interleaved buffers of samples from
// all of the Recordables it is listening to, which is probably not what you want.
//
// You'll notice that the three methods of this class are synchronized. This is because the samples methods
// will be called from a different thread than the one instances of this class will be created in. That thread
// might try to send samples to an instance of this class while the instance is in the middle of drawing the
// waveform, which would result in a waveform made up of samples from two different buffers. Synchronizing
// all the methods means that while the main thread of execution is inside draw, the thread that calls
// samples will block until draw is complete. Likewise, a call to draw will block if the sample thread is inside
// one of the samples methods. Hope that's not too confusing!
class WaveformRenderer implements AudioListener
{
private float[] left;
private float[] right;
WaveformRenderer()
{
left = null;
right = null;
}
synchronized void samples(float[] samp)
{
left = samp;
}
synchronized void samples(float[] sampL, float[] sampR)
{
left = sampL;
right = sampR;
}
synchronized void draw()
{
// we've got a stereo signal if right or left are not null
if ( left != null && right != null )
{
noFill();
stroke(255);
beginShape();
for ( int i = 0; i < left.length; i++ )
{
vertex(i, height/4 + left[i]*50);
}
endShape();
beginShape();
for ( int i = 0; i < right.length; i++ )
{
vertex(i, 3*(height/4) + right[i]*50);
}
endShape();
}
else if ( left != null )
{
noFill();
stroke(255);
beginShape();
for ( int i = 0; i < left.length; i++ )
{
vertex(i, height/2 + left[i]*50);
}
endShape();
}
}
}
Binary file not shown.
@@ -0,0 +1,71 @@
/**
* Band Pass Filter
* by Damien Di Fede.
*
* This sketch demonstrates how to use the BandPass effect.
* Move the mouse left and right to change the frequency of the pass band.
* Move the mouse up and down to change the band width of the pass band.
*/
import ddf.minim.*;
import ddf.minim.effects.*;
Minim minim;
AudioPlayer groove;
BandPass bpf;
void setup()
{
size(512, 200, P2D);
minim = new Minim(this);
groove = minim.loadFile("groove.mp3");
groove.loop();
// make a band pass filter with a center frequency of 440 Hz and a bandwidth of 20 Hz
// the third argument is the sample rate of the audio that will be filtered
// it is required to correctly compute values used by the filter
bpf = new BandPass(440, 20, groove.sampleRate());
groove.addEffect(bpf);
}
void draw()
{
background(0);
stroke(255);
// draw the waveforms
// the values returned by left.get() and right.get() will be between -1 and 1,
// so we need to scale them up to see the waveform
for(int i = 0; i < groove.right.size()-1; i++)
{
float x1 = map(i, 0, groove.bufferSize(), 0, width);
float x2 = map(i+1, 0, groove.bufferSize(), 0, width);
line(x1, height/4 - groove.left.get(i)*50, x2, height/4 - groove.left.get(i+1)*50);
line(x1, 3*height/4 - groove.right.get(i)*50, x2, 3*height/4 - groove.right.get(i+1)*50);
}
// draw a rectangle to represent the pass band
noStroke();
fill(255, 0, 0, 60);
rect(mouseX - bpf.getBandWidth()/20, 0, bpf.getBandWidth()/10, height);
}
void mouseMoved()
{
// map the mouse position to the range [100, 10000], an arbitrary range of passBand frequencies
float passBand = map(mouseX, 0, width, 100, 2000);
bpf.setFreq(passBand);
float bandWidth = map(mouseY, 0, height, 50, 500);
bpf.setBandWidth(bandWidth);
// prints the new values of the coefficients in the console
bpf.printCoeff();
}
void stop()
{
// always close Minim audio classes when you finish with them
groove.close();
// always stop Minim before exiting
minim.stop();
super.stop();
}
Binary file not shown.
+75
View File
@@ -0,0 +1,75 @@
/**
* Forward FFT
* by Damien Di Fede.
*
* This sketch demonstrates how to use an FFT to analyze an AudioBuffer
* and draw the resulting spectrum. It also allows you to turn windowing
* on and off, but you will see there is not much difference in the spectrum.
* Press 'w' to turn on windowing, press 'e' to turn it off.
*/
import ddf.minim.analysis.*;
import ddf.minim.*;
Minim minim;
AudioPlayer jingle;
FFT fft;
String windowName;
void setup()
{
size(512, 200);
minim = new Minim(this);
jingle = minim.loadFile("jingle.mp3", 2048);
jingle.loop();
// create an FFT object that has a time-domain buffer the same size as jingle's sample buffer
// note that this needs to be a power of two and that it means the size of the spectrum
// will be 512. see the online tutorial for more info.
fft = new FFT(jingle.bufferSize(), jingle.sampleRate());
textFont(createFont("SanSerif", 12));
windowName = "None";
}
void draw()
{
background(0);
stroke(255);
// perform a forward FFT on the samples in jingle's left buffer
// note that if jingle were a MONO file, this would be the same as using jingle.right or jingle.left
fft.forward(jingle.mix);
for(int i = 0; i < fft.specSize(); i++)
{
// draw the line for frequency band i, scaling it by 4 so we can see it a bit better
line(i, height, i, height - fft.getBand(i)*4);
}
fill(255);
// keep us informed about the window being used
text("The window being used is: " + windowName, 5, 20);
}
void keyReleased()
{
if ( key == 'w' )
{
// a Hamming window can be used to shape the sample buffer that is passed to the FFT
// this can reduce the amount of noise in the spectrum
fft.window(FFT.HAMMING);
windowName = "Hamming";
}
if ( key == 'e' )
{
fft.window(FFT.NONE);
windowName = "None";
}
}
void stop()
{
// always close Minim audio classes when you finish with them
jingle.close();
minim.stop();
super.stop();
}
Binary file not shown.
@@ -0,0 +1,22 @@
class BeatListener implements AudioListener
{
private BeatDetect beat;
private AudioPlayer source;
BeatListener(BeatDetect beat, AudioPlayer source)
{
this.source = source;
this.source.addListener(this);
this.beat = beat;
}
void samples(float[] samps)
{
beat.detect(source.mix);
}
void samples(float[] sampsL, float[] sampsR)
{
beat.detect(source.mix);
}
}
@@ -0,0 +1,82 @@
/**
* Frequency Energy
* by Damien Di Fede.
*
* This sketch demonstrates how to use the BeatDetect object in FREQ_ENERGY mode.
* You can use <code>isKick</code>, <code>isSnare</code>, </code>isHat</code>,
* <code>isRange</code>, and <code>isOnset(int)</code> to track whatever kind
* of beats you are looking to track, they will report true or false based on
* the state of the analysis. To "tick" the analysis you must call <code>detect</code>
* with successive buffers of audio. You can do this inside of <code>draw</code>,
* but you are likely to miss some audio buffers if you do this. The sketch implements
* an <code>AudioListener</code> called <code>BeatListener</code> so that it can call
* <code>detect</code> on every buffer of audio processed by the system without repeating
* a buffer or missing one.
*
* This sketch plays an entire song so it may be a little slow to load.
*/
import ddf.minim.*;
import ddf.minim.analysis.*;
Minim minim;
AudioPlayer song;
BeatDetect beat;
BeatListener bl;
float kickSize, snareSize, hatSize;
void setup()
{
size(512, 200);
smooth();
minim = new Minim(this);
song = minim.loadFile("marcus_kellis_theme.mp3", 2048);
song.play();
// a beat detection object that is FREQ_ENERGY mode that
// expects buffers the length of song's buffer size
// and samples captured at songs's sample rate
beat = new BeatDetect(song.bufferSize(), song.sampleRate());
// set the sensitivity to 300 milliseconds
// After a beat has been detected, the algorithm will wait for 300 milliseconds
// before allowing another beat to be reported. You can use this to dampen the
// algorithm if it is giving too many false-positives. The default value is 10,
// which is essentially no damping. If you try to set the sensitivity to a negative value,
// an error will be reported and it will be set to 10 instead.
beat.setSensitivity(300);
kickSize = snareSize = hatSize = 16;
// make a new beat listener, so that we won't miss any buffers for the analysis
bl = new BeatListener(beat, song);
textFont(createFont("SanSerif", 16));
textAlign(CENTER);
}
void draw()
{
background(0);
fill(255);
if ( beat.isKick() ) kickSize = 32;
if ( beat.isSnare() ) snareSize = 32;
if ( beat.isHat() ) hatSize = 32;
textSize(kickSize);
text("KICK", width/4, height/2);
textSize(snareSize);
text("SNARE", width/2, height/2);
textSize(hatSize);
text("HAT", 3*width/4, height/2);
kickSize = constrain(kickSize * 0.95, 16, 32);
snareSize = constrain(snareSize * 0.95, 16, 32);
hatSize = constrain(hatSize * 0.95, 16, 32);
}
void stop()
{
// always close Minim audio classes when you are finished with them
song.close();
// always stop Minim before exiting
minim.stop();
// this closes the sketch
super.stop();
}
+70
View File
@@ -0,0 +1,70 @@
/**
* Get Line In
* by Damien Di Fede.
*
* This sketch demonstrates how to use the <code>getLineIn</code> method of
* <code>Minim</code>. This method returns an <code>AudioInput</code> object.
* An <code>AudioInput</code> represents a connection to the computer's current
* record source (usually the line-in) and is used to monitor audio coming
* from an external source. There are five versions of <code>getLineIn</code>:
* <pre>
* getLineIn()
* getLineIn(int type)
* getLineIn(int type, int bufferSize)
* getLineIn(int type, int bufferSize, float sampleRate)
* getLineIn(int type, int bufferSize, float sampleRate, int bitDepth)
* </pre>
* The value you can use for <code>type</code> is either <code>Minim.MONO</code>
* or <code>Minim.STEREO</code>. <code>bufferSize</code> specifies how large
* you want the sample buffer to be, <code>sampleRate</code> specifies the
* sample rate you want to monitor at, and <code>bitDepth</code> specifies what
* bit depth you want to monitor at. <code>type</code> defaults to <code>Minim.STEREO</code>,
* <code>bufferSize</code> defaults to 1024, <code>sampleRate</code> defaults to
* 44100, and <code>bitDepth</code> defaults to 16. If an <code>AudioInput</code>
* cannot be created with the properties you request, <code>Minim</code> will report
* an error and return <code>null</code>.
*
* When you run your sketch as an applet you will need to sign it in order to get an input.
*
* Before you exit your sketch make sure you call the <code>close</code> method
* of any <code>AudioInput</code>'s you have received from <code>getLineIn</code>.
*/
import ddf.minim.*;
Minim minim;
AudioInput in;
void setup()
{
size(512, 200, P2D);
minim = new Minim(this);
minim.debugOn();
// get a line in from Minim, default bit depth is 16
in = minim.getLineIn(Minim.STEREO, 512);
}
void draw()
{
background(0);
stroke(255);
// draw the waveforms
for(int i = 0; i < in.bufferSize() - 1; i++)
{
line(i, 50 + in.left.get(i)*50, i+1, 50 + in.left.get(i+1)*50);
line(i, 150 + in.right.get(i)*50, i+1, 150 + in.right.get(i+1)*50);
}
}
void stop()
{
// always close Minim audio classes when you are done with them
in.close();
minim.stop();
super.stop();
}
+72
View File
@@ -0,0 +1,72 @@
/**
* Get Line Out
* by Damien Di Fede.
*
* This sketch demonstrates how to use the <code>getLineOut</code> method
* of <code>Minim</code>. This method returns an <code>AudioOutput</code>
* object. An <code>AudioOutput</code> represents a connection to the
* computer's speakers and is used to generate audio with <code>AudioSignal</code>s.
* There are five versions of <code>getLineOut</code>:
* <pre>
* getLineOut()
* getLineOut(int type)
* getLineOut(int type, int bufferSize)
* getLineOut(int type, int bufferSize, float sampleRate)
* getLineOut(int type, int bufferSize, float sampleRate, int bitDepth)
* </pre>
* The value you can use for <code>type</code> is either <code>Minim.MONO</code>
* or <code>Minim.STEREO</code>. <code>bufferSize</code> specifies how large
* you want the sample buffer to be, <code>sampleRate</code> specifies what
* the sample rate of the audio you will be generating is, and <code>bitDepth</code>
* specifies what the bit depth of the audio you will be generating is (8 or 16).
* <code>type</code> defaults to <code>Minim.STEREO</code>, <code>bufferSize</code>
* defaults to 1024, <code>sampleRate</code> defaults to 44100, and
* <code>bitDepth</code> defaults to 16.
*
* Before you exit your sketch make sure you call the <code>close</code>
* method of any <code>AudioOutput</code>'s you have received from <code>getLineOut</code>.
*/
import ddf.minim.*;
import ddf.minim.signals.*;
Minim minim;
AudioOutput out;
SineWave sine;
void setup()
{
size(512, 200, P2D);
minim = new Minim(this);
// get a line out from Minim, default sample rate is 44100, default bit depth is 16
out = minim.getLineOut(Minim.STEREO, 2048);
// create a sine wave Oscillator, set to 440 Hz, at 0.5 amplitude, sample rate 44100 to match the line out
sine = new SineWave(440, 0.5, out.sampleRate());
// add the oscillator to the line out
out.addSignal(sine);
}
void draw()
{
background(0);
stroke(255);
// draw the waveforms
for(int i = 0; i < out.bufferSize() - 1; i++)
{
line(i, 50 + out.left.get(i)*50, i+1, 50 + out.left.get(i+1)*50);
line(i, 150 + out.right.get(i)*50, i+1, 150 + out.right.get(i+1)*50);
}
}
void stop()
{
// always close Minim audio classes when you are done with them
out.close();
minim.stop();
super.stop();
}
+66
View File
@@ -0,0 +1,66 @@
/**
* Get Meta Data
* by Damien Di Fede.
*
* This sketch demonstrates how to use the <code>getMetaData</code>
* method of <code>AudioPlayer</code>. This method is also available
* for <code>AudioSnippet</code> and <code>AudioSample</code>.
* You should use this method when you want to retrieve metadata
* about a file that you have loaded, like ID3 tags from an mp3 file.
* If you load WAV file or other non-tagged file, most of the metadata
* will be empty, but you will still have information like the filename
* and the length.
*/
import ddf.minim.*;
Minim minim;
AudioPlayer groove;
AudioMetaData meta;
void setup()
{
size(512, 256, P2D);
minim = new Minim(this);
groove = minim.loadFile("groove.mp3");
meta = groove.getMetaData();
textFont(createFont("Serif", 12));
textMode(SCREEN);
}
int ys = 25;
int yi = 15;
void draw()
{
background(0);
int y = ys;
text("File Name: " + meta.fileName(), 5, y);
text("Length (in milliseconds): " + meta.length(), 5, y+=yi);
text("Title: " + meta.title(), 5, y+=yi);
text("Author: " + meta.author(), 5, y+=yi);
text("Album: " + meta.album(), 5, y+=yi);
text("Date: " + meta.date(), 5, y+=yi);
text("Comment: " + meta.comment(), 5, y+=yi);
text("Track: " + meta.track(), 5, y+=yi);
text("Genre: " + meta.genre(), 5, y+=yi);
text("Copyright: " + meta.copyright(), 5, y+=yi);
text("Disc: " + meta.disc(), 5, y+=yi);
text("Composer: " + meta.composer(), 5, y+=yi);
text("Orchestra: " + meta.orchestra(), 5, y+=yi);
text("Publisher: " + meta.publisher(), 5, y+=yi);
text("Encoded: " + meta.encoded(), 5, y+=yi);
}
void stop()
{
// always close Minim audio classes when you are done with them
groove.close();
// always stop Minim before exiting
minim.stop();
super.stop();
}
Binary file not shown.
Binary file not shown.
+77
View File
@@ -0,0 +1,77 @@
/**
* Get Set Pan
* by Damien Di Fede.
*
* This sketch demonstrates how to use the <code>getPan</code> and
* <code>setPan</code> methods of a <code>Controller</code> object.
* The class used here is an <code>AudioOutput</code> but you can also
* get and set the pan of <code>AudioSample</code>, <code>AudioSnippet</code>,
* <code>AudioInput</code>, and <code>AudioPlayer</code> objects.
* <code>getPan</code> and <code>setPan</code> will get and set the pan
* of the <code>DataLine</code> that is being used for input or output,
* but only if that line has a pan control. A <code>DataLine</code> is
* a low-level JavaSound class that is used for sending audio to,
* or receiving audio from, the audio system. You will notice in this
* sketch that you will hear the pan changing (if it's available) but you
* will not see any difference in the waveform being drawn. The reason
* for this is that what you see in the output's sample buffers is what
* it sends to the audio system. The system makes the pan change after
* receiving the samples.
*/
import ddf.minim.*;
import ddf.minim.signals.*;
Minim minim;
AudioOutput out;
Oscillator osc;
WaveformRenderer waveform;
void setup()
{
size(512, 200);
minim = new Minim(this);
out = minim.getLineOut();
// see the example AudioOutput >> SawWaveSignal for more about this class
osc = new SawWave(100, 0.2, out.sampleRate());
// see the example Polyphonic >> addSignal for more about this
out.addSignal(osc);
waveform = new WaveformRenderer();
// see the example Recordable >> addListener for more about this
out.addListener(waveform);
textFont(createFont("SanSerif", 12));
}
void draw()
{
background(0);
// see waveform.pde for more about this
waveform.draw();
if ( out.hasControl(Controller.PAN) )
{
// map the mouse position to the range of the pan
float val = map(mouseX, 0, width, -1, 1);
// if a pan control is not available, this will do nothing
out.setPan(val);
// if a pan control is not available this will report zero
text("The current pan is " + out.getPan() + ".", 5, 20);
}
else
{
text("The output doesn't have a pan control.", 5, 20);
}
}
void stop()
{
// always close Minim audio classes when you are finished with them
out.close();
minim.stop();
super.stop();
}
+76
View File
@@ -0,0 +1,76 @@
// This class is a very simple implementation of AudioListener. By implementing this interface,
// you can add instances of this class to any class in Minim that implements Recordable and receive
// buffers of samples in a callback fashion. In other words, every time that a Recordable object has
// a new buffer of samples, it will send a copy to all of its AudioListeners. You can add an instance of
// an AudioListener to a Recordable by using the addListener method of the Recordable. If you want to
// remove a listener that you previously added, you call the removeListener method of Recordable, passing
// the listener you want to remove.
//
// Although possible, it is not advised that you add the same listener to more than one Recordable.
// Your listener will be called any time any of the Recordables you've added it have new samples. This
// means that the stream of samples the listener sees will likely be interleaved buffers of samples from
// all of the Recordables it is listening to, which is probably not what you want.
//
// You'll notice that the three methods of this class are synchronized. This is because the samples methods
// will be called from a different thread than the one instances of this class will be created in. That thread
// might try to send samples to an instance of this class while the instance is in the middle of drawing the
// waveform, which would result in a waveform made up of samples from two different buffers. Synchronizing
// all the methods means that while the main thread of execution is inside draw, the thread that calls
// samples will block until draw is complete. Likewise, a call to draw will block if the sample thread is inside
// one of the samples methods. Hope that's not too confusing!
class WaveformRenderer implements AudioListener
{
private float[] left;
private float[] right;
WaveformRenderer()
{
left = null;
right = null;
}
synchronized void samples(float[] samp)
{
left = samp;
}
synchronized void samples(float[] sampL, float[] sampR)
{
left = sampL;
right = sampR;
}
synchronized void draw()
{
// we've got a stereo signal if right is not null
if ( left != null && right != null )
{
noFill();
stroke(255);
beginShape();
for ( int i = 0; i < left.length; i++ )
{
vertex(i, height/4 + left[i]*50);
}
endShape();
beginShape();
for ( int i = 0; i < right.length; i++ )
{
vertex(i, 3*(height/4) + right[i]*50);
}
endShape();
}
else if ( left != null )
{
noFill();
stroke(255);
beginShape();
for ( int i = 0; i < left.length; i++ )
{
vertex(i, height/2 + left[i]*50);
}
endShape();
}
}
}
@@ -0,0 +1,58 @@
/**
* Linear Averages
* by Damien Di Fede.
*
* This sketch demonstrates how to use the averaging abilities of the FFT.
* 128 linearly spaced averages are requested and then those are drawn as rectangles.
*/
import ddf.minim.analysis.*;
import ddf.minim.*;
Minim minim;
AudioPlayer jingle;
FFT fft;
void setup()
{
size(512, 200, P2D);
minim = new Minim(this);
jingle = minim.loadFile("jingle.mp3", 2048);
// loop the file
jingle.loop();
// create an FFT object that has a time-domain buffer the same size as jingle's sample buffer
// and a sample rate that is the same as jingle's
// note that this needs to be a power of two
// and that it means the size of the spectrum will be 1024.
// see the online tutorial for more info.
fft = new FFT(jingle.bufferSize(), jingle.sampleRate());
// use 128 averages.
// the maximum number of averages we could ask for is half the spectrum size.
fft.linAverages(128);
rectMode(CORNERS);
}
void draw()
{
background(0);
fill(255);
// perform a forward FFT on the samples in jingle's mix buffer
// note that if jingle were a MONO file, this would be the same as using jingle.left or jingle.right
fft.forward(jingle.mix);
int w = int(fft.specSize()/128);
for(int i = 0; i < fft.avgSize(); i++)
{
// draw a rectangle for each average, multiply the value by 5 so we can see it better
rect(i*w, height, i*w + w, height - fft.getAvg(i)*5);
}
}
void stop()
{
// always close Minim audio classes when you finish with them
jingle.close();
minim.stop();
super.stop();
}
Binary file not shown.
+67
View File
@@ -0,0 +1,67 @@
/**
* Load File
* by Damien Di Fede.
*
* This sketch demonstrates how to use the <code>loadFile</code> method
* of <code>Minim</code>. The <code>loadFile</code> method allows you to
* specify the file you want to load with a <code>String</code> and optionally
* specify what you want the buffer size of the returned <code>AudioPlayer</code>
* to be. If you don't specify a buffer size, the returned player will have a
* buffer size of 1024. Minim is able to play wav files, au files, aif files,
* snd files, and mp3 files. When you call <code>loadFile</code>, if you just
* specify the filename it will try to load the file from the data folder of
* your sketch. However, you can also specify an absolute path
* (such as "C:\foo\bar\thing.wav") and the file will be loaded from that
* location (keep in mind that won't work from an applet). You can also specify
* a URL (such as "http://www.mysite.com/mp3/song.mp3") but keep in mind that
* if you run the sketch as an applet you may run in to security restrictions
* if the applet is not on the same domain as the file you want to load. You can
* get around the restriction by signing the applet. Before you exit your sketch
* make sure you call the <code>close</code> method of any <code>AudioPlayer</code>'s
* you have received from <code>loadFile</code>, followed by the <code>stop</code>
* method of <code>Minim</code>.
*/
import ddf.minim.*;
AudioPlayer player;
Minim minim;
void setup()
{
size(512, 200, P2D);
minim = new Minim(this);
// load a file, give the AudioPlayer buffers that are 1024 samples long
// player = minim.loadFile("groove.mp3");
// load a file, give the AudioPlayer buffers that are 2048 samples long
player = minim.loadFile("groove.mp3", 2048);
// play the file
player.play();
}
void draw()
{
background(0);
stroke(255);
// draw the waveforms
// the values returned by left.get() and right.get() will be between -1 and 1,
// so we need to scale them up to see the waveform
// note that if the file is MONO, left.get() and right.get() will return the same value
for(int i = 0; i < player.left.size()-1; i++)
{
line(i, 50 + player.left.get(i)*50, i+1, 50 + player.left.get(i+1)*50);
line(i, 150 + player.right.get(i)*50, i+1, 150 + player.right.get(i+1)*50);
}
}
void stop()
{
// always close Minim audio classes when you are done with them
player.close();
minim.stop();
super.stop();
}
Binary file not shown.
+77
View File
@@ -0,0 +1,77 @@
/**
* Load Sample
* by Damien Di Fede.
*
* This sketch demonstrates how to use the <code>loadSample</code>
* method of <code>Minim</code>. The <code>loadSample</code>
* method allows you to specify the sample you want to load with
* a <code>String</code> and optionally specify what you
* want the buffer size of the returned <code>AudioSample</code>
* to be. If you don't specify a buffer size, the returned sample
* will have a buffer size of 1024. Minim is able to load wav files,
* au files, aif files, snd files, and mp3 files. When you call
* <code>loadSample</code>, if you just specify the filename it will
* try to load the sample from the data folder of your sketch. However,
* you can also specify an absolute path (such as "C:\foo\bar\thing.wav")
* and the file will be loaded from that location (keep in mind that
* won't work from an applet). You can also specify a URL (such as
* "http://www.mysite.com/mp3/song.mp3") but keep in mind that if you
* run the sketch as an applet you may run in to security restrictions
* if the applet is not on the same domain as the file you want to load.
* You can get around the restriction by signing the applet. Before you
* exit your sketch make sure you call the <code>close</code> method
* of any <code>AudioSamples</code>'s you have received from
* <code>loadSample</code>.
*
* An <code>AudioSample</code> is a special kind of file playback that
* allows you to repeatedly <i>trigger</i> an audio file. It does this
* by keeping the entire file in an internal buffer and then keeping a
* list of trigger points. <code>AudioSample</code> supports up to 20
* overlapping triggers, which should be plenty for short sounds. It is
* not advised that you use this class for long sounds (like entire songs,
* for example) because the entire file is kept in memory.
*
* Press 'k' to trigger the sample.
*/
import ddf.minim.*;
Minim minim;
AudioSample kick;
void setup()
{
size(512, 200, P2D);
// always start Minim before you do anything with it
minim = new Minim(this);
// load BD.mp3 from the data folder with a 1024 sample buffer
// kick = Minim.loadSample("BD.mp3");
// load BD.mp3 from the data folder, with a 512 sample buffer
kick = minim.loadSample("BD.mp3", 2048);
}
void draw()
{
background(0);
stroke(255);
// use the mix buffer to draw the waveforms.
// because these are MONO files, we could have used the left or right buffers and got the same data
for (int i = 0; i < kick.bufferSize() - 1; i++)
{
line(i, 100 - kick.left.get(i)*50, i+1, 100 - kick.left.get(i+1)*50);
}
}
void keyPressed()
{
if ( key == 'k' ) kick.trigger();
}
void stop()
{
// always close Minim audio classes when you are done with them
kick.close();
minim.stop();
super.stop();
}
Binary file not shown.
+68
View File
@@ -0,0 +1,68 @@
/**
* Load Snippet
* by Damien Di Fede.
*
* This sketch demonstrates how to use the <code>loadSnippet</code>
* method of <code>Minim</code>. The <code>loadSnippet</code> method
* allows you to specify the file you want to load with a
* <code>String</code>. Unlike with <code>loadFile</code> and <code>loadSample</code>,
* you are not able to specify a buffer size because an <code>AudioSnippet</code>
* doesn't give you access to the samples as they are played.
*
* Minim is able to load wav files, au files, aif files, snd files, and mp3
* files. When you call <code>loadSnippet</code>, if you just specify the
* filename it will try to load the file from the data folder of your sketch.
* However, you can also specify an absolute path (such as "C:\foo\bar\thing.wav")
* and the file will be loaded from that location (keep in mind that won't
* work from an applet). You can also specify a URL (such as
* "http://www.mysite.com/mp3/song.mp3") but keep in mind that if you run the
* sketch as an applet you may run in to security restrictions if the applet
* is not on the same domain as the file you want to load. You can get around the
* restriction by signing the applet.
*
* <code>AudioSnippet</code> is a simple wrapper around a JavaSound <code>Clip</code>
* (It isn't called AudioClip because that's an interface defined in the package
* java.applet). It provides almost the exact same functionality, the main
* difference being that length, position, and cue are expressed in milliseconds
* instead of microseconds. One of the limitations of <code>AudioSnippet</code> is
* that you do not have access to the audio samples as they are played. However,
* you are spared all of the overhead associated with making samples available.
* An <code>AudioSnippet</code> is a good choice if all you need to do is play
* a short sound at some point. If your aim is to repeatedly trigger a sound, you
* should use an <code>AudioSample</code> instead.
*
* Before you exit your sketch make sure you call the <code>close</code>
* method of any <code>AudioSnippet</code>'s you have received from
* <code>loadSnippet</code>.
*/
import ddf.minim.*;
Minim minim;
AudioSnippet snip;
void setup()
{
size(512, 200);
minim = new Minim(this);
snip = minim.loadSnippet("groove.mp3");
// play the file
snip.play();
}
void draw()
{
background(0);
// there are no waveforms to draw
}
void stop()
{
// always close Minim audio classes when you are done with them
snip.close();
// always stop Minim before exiting
minim.stop();
super.stop();
}
Binary file not shown.
+101
View File
@@ -0,0 +1,101 @@
/**
* Record Line In
* by Damien Di Fede.
*
* This sketch demonstrates how to an <code>AudioRecorder</code>
* to record audio to disk. To use this sketch you need to have
* something plugged into the line-in on your computer. Press 'r'
* to toggle recording on and off and the press 's' to save to disk.
* The recorded file will be placed in the sketch folder of
* the sketch.
*/
import ddf.minim.*;
Minim minim;
AudioInput in;
AudioRecorder recorder;
void setup()
{
size(512, 200, P2D);
textMode(SCREEN);
minim = new Minim(this);
// get a stereo line-in: sample buffer length of 2048
// default sample rate is 44100, default bit depth is 16
in = minim.getLineIn(Minim.STEREO, 2048);
// create a recorder that will record from the input to the filename specified, using buffered recording
// buffered recording means that all captured audio will be written into a sample buffer
// then when save() is called, the contents of the buffer will actually be written to a file
// the file will be located in the sketch's root folder.
recorder = minim.createRecorder(in, "myrecording.wav", true);
textFont(createFont("SanSerif", 12));
}
void draw()
{
background(0);
stroke(255);
// draw the waveforms
// the values returned by left.get() and right.get() will be between -1 and 1,
// so we need to scale them up to see the waveform
for(int i = 0; i < in.bufferSize() - 1; i++)
{
line(i, 50 + in.left.get(i)*50, i+1, 50 + in.left.get(i+1)*50);
line(i, 150 + in.right.get(i)*50, i+1, 150 + in.right.get(i+1)*50);
}
if ( recorder.isRecording() )
{
text("Currently recording...", 5, 15);
}
else
{
text("Not recording.", 5, 15);
}
}
void keyReleased()
{
if ( key == 'r' )
{
// to indicate that you want to start or stop capturing audio data, you must call
// beginRecord() and endRecord() on the AudioRecorder object. You can start and stop
// as many times as you like, the audio data will be appended to the end of the buffer
// (in the case of buffered recording) or to the end of the file (in the case of streamed recording).
if ( recorder.isRecording() )
{
recorder.endRecord();
}
else
{
recorder.beginRecord();
}
}
if ( key == 's' )
{
// we've filled the file out buffer,
// now write it to the file we specified in createRecorder
// in the case of buffered recording, if the buffer is large,
// this will appear to freeze the sketch for sometime
// in the case of streamed recording,
// it will not freeze as the data is already in the file and all that is being done
// is closing the file.
// the method returns the recorded audio as an AudioRecording,
// see the example AudioRecorder >> RecordAndPlayback for more about that
recorder.save();
println("Done saving.");
}
}
void stop()
{
// always close Minim audio classes when you are done with them
in.close();
minim.stop();
super.stop();
}
@@ -0,0 +1,80 @@
/**
* Sine Wave Signal
* by Damien Di Fede.
*
* This sketch demonstrates how to use a <code>SineWave</code> with
* an <code>AudioOutput</code>. Move the mouse up and down to change
* the frequency, left and right to change the panning.
*
* <code>SineWave</code> is a subclass of <code>Oscillator</code>, which
* is an abstract class that implements the interface <code>AudioSignal</code>.
* This means that it can be added to an <code>AudioOutput</code> and the
* <code>AudioOutput</code> will call one of the two <code>generate()</code>
* functions, depending on whether the AudioOutput is STEREO or MONO.
* Since it is an abstract class, it can't be directly instantiated, it
* merely provides the functionality of smoothly changing frequency, amplitude
* and pan. In order to have an <code>Oscillator</code> that actually
* produces sound, you have to extend <code>Oscillator</code> and define
* the value function. This function takes a <b>step</b> value and returns
* a sample value between -1 and 1. In the case of the SineWave,
* the value function returns this: <b>sin(freq * TWO_PI * step)</b>
* <b>freq</b> is the current frequency (in Hertz) of the <code>Oscillator</code>.
* It is multiplied by <b>TWO_PI</b> to set the period of the sine wave
* properly and then that sine wave is sampled at <b>step</b>.
*/
import ddf.minim.*;
import ddf.minim.signals.*;
Minim minim;
AudioOutput out;
SineWave sine;
void setup()
{
size(512, 200, P2D);
minim = new Minim(this);
// get a line out from Minim, default bufferSize is 1024, default sample rate is 44100, bit depth is 16
out = minim.getLineOut(Minim.STEREO);
// create a sine wave Oscillator, set to 440 Hz, at 0.5 amplitude, sample rate from line out
sine = new SineWave(440, 0.5, out.sampleRate());
// set the portamento speed on the oscillator to 200 milliseconds
sine.portamento(200);
// add the oscillator to the line out
out.addSignal(sine);
}
void draw()
{
background(0);
stroke(255);
// draw the waveforms
for(int i = 0; i < out.bufferSize() - 1; i++)
{
float x1 = map(i, 0, out.bufferSize(), 0, width);
float x2 = map(i+1, 0, out.bufferSize(), 0, width);
line(x1, 50 + out.left.get(i)*50, x2, 50 + out.left.get(i+1)*50);
line(x1, 150 + out.right.get(i)*50, x2, 150 + out.right.get(i+1)*50);
}
}
void mouseMoved()
{
// with portamento on the frequency will change smoothly
float freq = map(mouseY, 0, height, 1500, 60);
sine.setFreq(freq);
// pan always changes smoothly to avoid crackles getting into the signal
// note that we could call setPan on out, instead of on sine
// this would sound the same, but the waveforms in out would not reflect the panning
float pan = map(mouseX, 0, width, -1, 1);
sine.setPan(pan);
}
void stop()
{
out.close();
minim.stop();
super.stop();
}
@@ -0,0 +1,23 @@
// this is a really straightforward effect that just reverses the order of the samples it receives
// it doesn't sound like how you think ;-)
class ReverseEffect implements AudioEffect
{
void process(float[] samp)
{
float[] reversed = new float[samp.length];
int i = samp.length - 1;
for (int j = 0; j < reversed.length; i--, j++)
{
reversed[j] = samp[i];
}
// we have to copy the values back into samp for this to work
arraycopy(reversed, samp);
}
void process(float[] left, float[] right)
{
process(left);
process(right);
}
}
@@ -0,0 +1,50 @@
/**
* User Defined Effect
* by Damien Di Fede.
*
* This sketch demonstrates how to write your own AudioEffect.
* See NoiseEffect.pde for the implementation.
*/
import ddf.minim.*;
import ddf.minim.effects.*;
Minim minim;
AudioPlayer groove;
ReverseEffect reffect;
void setup()
{
size(512, 200, P2D);
minim = new Minim(this);
// try changing the buffer size to see how it changes the effect
groove = minim.loadFile("groove.mp3", 2048);
groove.loop();
reffect = new ReverseEffect();
groove.addEffect(reffect);
}
void draw()
{
background(0);
stroke(255);
// we multiply the values returned by get by 50 so we can see the waveform
for ( int i = 0; i < groove.bufferSize() - 1; i++ )
{
float x1 = map(i, 0, groove.bufferSize(), 0, width);
float x2 = map(i+1, 0, groove.bufferSize(), 0, width);
line(x1, height/4 - groove.left.get(i)*50, x2, height/4 - groove.left.get(i+1)*50);
line(x1, 3*height/4 - groove.right.get(i)*50, x2, 3*height/4 - groove.right.get(i+1)*50);
}
}
void stop()
{
// always close Minim audio classes when you finish with them
groove.close();
// always stop Minim before exiting
minim.stop();
super.stop();
}
Binary file not shown.
@@ -0,0 +1,24 @@
// this signal uses the mouseX and mouseY position to build a signal
class MouseSaw implements AudioSignal
{
void generate(float[] samp)
{
float range = map(mouseX, 0, width, 0, 1);
float peaks = map(mouseY, 0, height, 1, 20);
float inter = float(samp.length) / peaks;
for ( int i = 0; i < samp.length; i += inter )
{
for ( int j = 0; j < inter && (i+j) < samp.length; j++ )
{
samp[i + j] = map(j, 0, inter, -range, range);
}
}
}
// this is a stricly mono signal
void generate(float[] left, float[] right)
{
generate(left);
generate(right);
}
}
@@ -0,0 +1,48 @@
/**
* User Defined Signal
* by Damien Di Fede.
*
* This sketch demonstrates how to implement your own AudioSignal
* for Minim. See MouseSaw.pde for the implementation.
*/
import ddf.minim.*;
import ddf.minim.signals.*;
Minim minim;
AudioOutput out;
MouseSaw msaw;
void setup()
{
size(512, 200, P2D);
minim = new Minim(this);
out = minim.getLineOut(Minim.STEREO, 2048);
msaw = new MouseSaw();
// adds the signal to the output
out.addSignal(msaw);
}
void draw()
{
background(0);
stroke(255);
// draw the waveforms
for(int i = 0; i < out.bufferSize()-1; i++)
{
float x1 = map(i, 0, out.bufferSize(), 0, width);
float x2 = map(i+1, 0, out.bufferSize(), 0, width);
line(x1, 50 + out.left.get(i)*50, x2, 50 + out.left.get(i+1)*50);
line(x1, 150 + out.right.get(i)*50, x2, 150 + out.right.get(i+1)*50);
}
}
void stop()
{
out.close();
minim.stop();
super.stop();
}
@@ -0,0 +1,85 @@
/**
* Carnivore Client
* by Alexander R. Galloway.
* The Carnivore library for Processing allows the programmer to run a packet
* sniffer from within the Processing environment. A packet sniffer is any
* application that is able to indiscriminately eavesdrop on data traffic
* traveling through a local area network (LAN).
*
* Note: requires Carnivore Library for Processing v2.2 (http://r-s-g.org/carnivore)
* Windows, first install winpcap (http://winpcap.org)
* Mac, first open a Terminal and execute this commmand: sudo chmod 777 /dev/bpf*
* (must be done each time you reboot your mac)
*/
import java.util.Iterator;
import org.rsg.carnivore.*;
import org.rsg.carnivore.net.*;
HashMap nodes = new HashMap();
float startDiameter = 100.0;
float shrinkSpeed = 0.97;
int splitter, x, y;
PFont font;
void setup()
{
size(800, 600);
background(255);
frameRate(10);
Log.setDebug(true); // Uncomment this for verbose mode
CarnivoreP5 c = new CarnivoreP5(this);
//c.setVolumeLimit(4);
// Use the "Create Font" tool to add a 12 point font to your sketch,
// then use its name as the parameter to loadFont().
font = loadFont("CourierNew-12.vlw");
textFont(font);
}
void draw()
{
background(255);
drawNodes();
}
// Iterate through each node
synchronized void drawNodes() {
Iterator it = nodes.keySet().iterator();
while (it.hasNext()) {
String ip = (String)it.next();
float d = float(nodes.get(ip).toString());
// Use last two IP address bytes for x/y coords
splitter = ip.lastIndexOf(".");
y = int(ip.substring(splitter + 1)) * height / 255; // Scale to applet size
String tmp = ip.substring(0, splitter);
splitter = tmp.lastIndexOf(".");
x = int(tmp.substring(splitter + 1)) * width / 255; // Scale to applet size
// Draw the node
stroke(0);
fill(color(100, 200)); // Rim
ellipse(x, y, d, d); // Node circle
noStroke();
fill(color(100, 50)); // Halo
ellipse(x, y, d + 20, d + 20);
// Draw the text
fill(0);
text(ip, x, y);
// Shrink the nodes a little
nodes.put(ip, str(d * shrinkSpeed));
}
}
// Called each time a new packet arrives
synchronized void packetEvent(CarnivorePacket packet)
{
println("[PDE] packetEvent: " + packet);
// Remember these nodes in our hash map
nodes.put(packet.receiverAddress.toString(), str(startDiameter));
nodes.put(packet.senderAddress.toString(), str(startDiameter));
}
@@ -0,0 +1,52 @@
/**
* Chat Server
* by Tom Igoe.
*
* Press the mouse to stop the server.
*/
import processing.net.*;
int port = 10002;
boolean myServerRunning = true;
int bgColor = 0;
int direction = 1;
int textLine = 60;
Server myServer;
void setup()
{
size(400, 400);
textFont(createFont("SanSerif", 16));
myServer = new Server(this, port); // Starts a myServer on port 10002
background(0);
}
void mousePressed()
{
// If the mouse clicked the myServer stops
myServer.stop();
myServerRunning = false;
}
void draw()
{
if (myServerRunning == true)
{
text("server", 15, 45);
Client thisClient = myServer.available();
if (thisClient != null) {
if (thisClient.available() > 0) {
text("mesage from: " + thisClient.ip() + " : " + thisClient.readString(), 15, textLine);
textLine = textLine + 35;
}
}
}
else
{
text("server", 15, 45);
text("stopped", 15, 65);
}
}
@@ -0,0 +1,29 @@
/**
* HTTP Client.
*
* Starts a network client that connects to a server on port 80,
* sends an HTTP 1.1 GET request, and prints the results.
*/
import processing.net.*;
Client c;
String data;
void setup() {
size(200, 200);
background(50);
fill(200);
c = new Client(this, "www.processing.org", 80); // Connect to server on port 80
c.write("GET / HTTP/1.1\n"); // Use the HTTP "GET" command to ask for a Web page
c.write("Host: my_domain_name.com\n\n"); // Be polite and say who we are
}
void draw() {
if (c.available() > 0) { // If there's incoming data from the client...
data = c.readString(); // ...then grab it and print it
println(data);
}
}
@@ -0,0 +1,46 @@
/**
* Shared Drawing Canvas (Client)
* by Alexander R. Galloway.
*
* The Processing Client class is instantiated by specifying a remote
* address and port number to which the socket connection should be made.
* Once the connection is made, the client may read (or write) data to the server.
* Before running this program, start the Shared Drawing Canvas (Server) program.
*/
import processing.net.*;
Client c;
String input;
int data[];
void setup()
{
size(450, 255);
background(204);
stroke(0);
frameRate(5); // Slow it down a little
// Connect to the server's IP address and port
c = new Client(this, "127.0.0.1", 12345); // Replace with your server's IP and port
}
void draw()
{
if (mousePressed == true) {
// Draw our line
stroke(255);
line(pmouseX, pmouseY, mouseX, mouseY);
// Send mouse coords to other person
c.write(pmouseX + " " + pmouseY + " " + mouseX + " " + mouseY + "\n");
}
// Receive data from server
if (c.available() > 0) {
input = c.readString();
input = input.substring(0, input.indexOf("\n")); // Only up to the newline
data = int(split(input, ' ')); // Split values into an array
// Draw line using received coords
stroke(0);
line(data[0], data[1], data[2], data[3]);
}
}
@@ -0,0 +1,50 @@
/**
* Shared Drawing Canvas (Server)
* by Alexander R. Galloway.
*
* A server that shares a drawing canvas between two computers.
* In order to open a socket connection, a server must select a
* port on which to listen for incoming clients and through which
* to communicate. Once the socket is established, a client may
* connect to the server and send or receive commands and data.
* Get this program running and then start the Shared Drawing
* Canvas (Client) program so see how they interact.
*/
import processing.net.*;
Server s;
Client c;
String input;
int data[];
void setup()
{
size(450, 255);
background(204);
stroke(0);
frameRate(5); // Slow it down a little
s = new Server(this, 12345); // Start a simple server on a port
}
void draw()
{
if (mousePressed == true) {
// Draw our line
stroke(255);
line(pmouseX, pmouseY, mouseX, mouseY);
// Send mouse coords to other person
s.write(pmouseX + " " + pmouseY + " " + mouseX + " " + mouseY + "\n");
}
// Receive data from client
c = s.available();
if (c != null) {
input = c.readString();
input = input.substring(0, input.indexOf("\n")); // Only up to the newline
data = int(split(input, ' ')); // Split values into an array
// Draw line using received coords
stroke(0);
line(data[0], data[1], data[2], data[3]);
}
}
@@ -0,0 +1,50 @@
/**
* Yahoo! Search.
*
* Download the Yahoo! Search SDK from http://developer.yahoo.com/download
* Inside the download, find the yahoo_search-2.X.X.jar file somewhere inside
* the "Java" subdirectory. Drag the jar file to your sketch and it will be
* added to your 'code' folder for use.
*
* This example is based on the based on Yahoo! API example.
*/
// Replace this with a developer key from http://developer.yahoo.com
String appid = "YOUR_DEVELOPER_KEY_HERE";
SearchClient client = new SearchClient(appid);
String query = "processing.org";
WebSearchRequest request = new WebSearchRequest(query);
// (Optional) Set the maximum number of results to download
//request.setResults(30);
try {
WebSearchResults results = client.webSearch(request);
// Print out how many hits were found
println("Displaying " + results.getTotalResultsReturned() +
" out of " + results.getTotalResultsAvailable() + " hits.");
println();
// Get a list of the search results
WebSearchResult[] resultList = results.listResults();
// Loop through the results and print them to the console
for (int i = 0; i < resultList.length; i++) {
// Print out the document title and URL.
println((i + 1) + ".");
println(resultList[i].getTitle());
println(resultList[i].getUrl());
println();
}
// Error handling below, see the documentation of the Yahoo! API for details
}
catch (IOException e) {
println("Error calling Yahoo! Search Service: " + e.toString());
e.printStackTrace();
}
catch (SearchException e) {
println("Error calling Yahoo! Search Service: " + e.toString());
e.printStackTrace();
}
@@ -0,0 +1,87 @@
/**
* Esfera
* by David Pena.
*
* Distribucion aleatoria uniforme sobre la superficie de una esfera.
*/
import processing.opengl.*;
int cuantos = 8000;
pelo[] lista ;
float[] z = new float[cuantos];
float[] phi = new float[cuantos];
float[] largos = new float[cuantos];
float radio = 200;
float rx = 0;
float ry =0;
void setup() {
size(1024, 768, OPENGL);
radio = height/3.5;
lista = new pelo[cuantos];
for (int i=0; i<cuantos; i++){
lista[i] = new pelo();
}
noiseDetail(3);
}
void draw() {
background(0);
translate(width/2,height/2);
float rxp = ((mouseX-(width/2))*0.005);
float ryp = ((mouseY-(height/2))*0.005);
rx = (rx*0.9)+(rxp*0.1);
ry = (ry*0.9)+(ryp*0.1);
rotateY(rx);
rotateX(ry);
fill(0);
noStroke();
sphere(radio);
for (int i=0;i<cuantos;i++){
lista[i].dibujar();
}
}
class pelo
{
float z = random(-radio,radio);
float phi = random(TWO_PI);
float largo = random(1.15,1.2);
float theta = asin(z/radio);
void dibujar(){
float off = (noise(millis() * 0.0005,sin(phi))-0.5) * 0.3;
float offb = (noise(millis() * 0.0007,sin(z) * 0.01)-0.5) * 0.3;
float thetaff = theta+off;
float phff = phi+offb;
float x = radio * cos(theta) * cos(phi);
float y = radio * cos(theta) * sin(phi);
float z = radio * sin(theta);
float msx= screenX(x,y,z);
float msy= screenY(x,y,z);
float xo = radio * cos(thetaff) * cos(phff);
float yo = radio * cos(thetaff) * sin(phff);
float zo = radio * sin(thetaff);
float xb = xo * largo;
float yb = yo * largo;
float zb = zo * largo;
beginShape(LINES);
stroke(0);
vertex(x,y,z);
stroke(200,150);
vertex(xb,yb,zb);
endShape();
}
}
@@ -0,0 +1,52 @@
/**
* Extrusion.
*
* Converts a flat image into spatial data points and rotates the points
* around the center.
*/
import processing.opengl.*;
PImage a;
boolean onetime = true;
int[][] aPixels;
int[][] values;
float angle;
void setup() {
size(1024, 768, OPENGL);
aPixels = new int[width][height];
values = new int[width][height];
noFill();
// Load the image into a new array
// Extract the values and store in an array
a = loadImage("ystone08.jpg");
a.loadPixels();
for (int i = 0; i < a.height; i++) {
for (int j = 0; j < a.width; j++) {
aPixels[j][i] = a.pixels[i*a.width + j];
values[j][i] = int(blue(aPixels[j][i]));
}
}
}
void draw() {
background(255);
translate(width/2, height/2, 0);
scale(2.0);
// Update and constrain the angle
angle += 0.005;
rotateY(angle);
// Display the image mass
for (int i = 0; i < a.height; i += 2) {
for (int j = 0; j < a.width; j += 2) {
stroke(values[j][i], 153);
line(j-a.width/2, i-a.height/2, -values[j][i], j-a.width/2, i-a.height/2, -values[j][i]-10);
}
}
}
@@ -0,0 +1,165 @@
/**
* Geometry
* by Marius Watz.
*
* Using sin/cos lookup tables, blends colors, and draws a series of
* rotating arcs on the screen.
*/
import processing.opengl.*;
// Trig lookup tables borrowed from Toxi; cryptic but effective.
float sinLUT[];
float cosLUT[];
float SINCOS_PRECISION=1.0;
int SINCOS_LENGTH= int((360.0/SINCOS_PRECISION));
// System data
boolean dosave=false;
int num;
float pt[];
int style[];
void setup() {
size(1024, 768, OPENGL);
background(255);
// Fill the tables
sinLUT=new float[SINCOS_LENGTH];
cosLUT=new float[SINCOS_LENGTH];
for (int i = 0; i < SINCOS_LENGTH; i++) {
sinLUT[i]= (float)Math.sin(i*DEG_TO_RAD*SINCOS_PRECISION);
cosLUT[i]= (float)Math.cos(i*DEG_TO_RAD*SINCOS_PRECISION);
}
num = 150;
pt = new float[6*num]; // rotx, roty, deg, rad, w, speed
style = new int[2*num]; // color, render style
// Set up arc shapes
int index=0;
float prob;
for (int i=0; i<num; i++) {
pt[index++] = random(PI*2); // Random X axis rotation
pt[index++] = random(PI*2); // Random Y axis rotation
pt[index++] = random(60,80); // Short to quarter-circle arcs
if(random(100)>90) pt[index]=(int)random(8,27)*10;
pt[index++] = int(random(2,50)*5); // Radius. Space them out nicely
pt[index++] = random(4,32); // Width of band
if(random(100)>90) pt[index]=random(40,60); // Width of band
pt[index++] = radians(random(5,30))/5; // Speed of rotation
// get colors
prob = random(100);
if(prob<30) style[i*2]=colorBlended(random(1), 255,0,100, 255,0,0, 210);
else if(prob<70) style[i*2]=colorBlended(random(1), 0,153,255, 170,225,255, 210);
else if(prob<90) style[i*2]=colorBlended(random(1), 200,255,0, 150,255,0, 210);
else style[i*2]=color(255,255,255, 220);
if(prob<50) style[i*2]=colorBlended(random(1), 200,255,0, 50,120,0, 210);
else if(prob<90) style[i*2]=colorBlended(random(1), 255,100,0, 255,255,0, 210);
else style[i*2]=color(255,255,255, 220);
style[i*2+1]=(int)(random(100))%3;
}
}
void draw() {
background(0);
int index=0;
translate(width/2, height/2, 0);
rotateX(PI/6);
rotateY(PI/6);
for (int i = 0; i < num; i++) {
pushMatrix();
rotateX(pt[index++]);
rotateY(pt[index++]);
if(style[i*2+1]==0) {
stroke(style[i*2]);
noFill();
strokeWeight(1);
arcLine(0,0, pt[index++],pt[index++],pt[index++]);
}
else if(style[i*2+1]==1) {
fill(style[i*2]);
noStroke();
arcLineBars(0,0, pt[index++],pt[index++],pt[index++]);
}
else {
fill(style[i*2]);
noStroke();
arc(0,0, pt[index++],pt[index++],pt[index++]);
}
// increase rotation
pt[index-5]+=pt[index]/10;
pt[index-4]+=pt[index++]/20;
popMatrix();
}
}
// Get blend of two colors
int colorBlended(float fract,
float r, float g, float b,
float r2, float g2, float b2, float a) {
r2 = (r2 - r);
g2 = (g2 - g);
b2 = (b2 - b);
return color(r + r2 * fract, g + g2 * fract, b + b2 * fract, a);
}
// Draw arc line
void arcLine(float x,float y,float deg,float rad,float w) {
int a=(int)(min (deg/SINCOS_PRECISION,SINCOS_LENGTH-1));
int numlines=(int)(w/2);
for (int j=0; j<numlines; j++) {
beginShape();
for (int i=0; i<a; i++) {
vertex(cosLUT[i]*rad+x,sinLUT[i]*rad+y);
}
endShape();
rad += 2;
}
}
// Draw arc line with bars
void arcLineBars(float x,float y,float deg,float rad,float w) {
int a = int((min (deg/SINCOS_PRECISION,SINCOS_LENGTH-1)));
a /= 4;
beginShape(QUADS);
for (int i=0; i<a; i+=4) {
vertex(cosLUT[i]*(rad)+x,sinLUT[i]*(rad)+y);
vertex(cosLUT[i]*(rad+w)+x,sinLUT[i]*(rad+w)+y);
vertex(cosLUT[i+2]*(rad+w)+x,sinLUT[i+2]*(rad+w)+y);
vertex(cosLUT[i+2]*(rad)+x,sinLUT[i+2]*(rad)+y);
}
endShape();
}
// Draw solid arc
void arc(float x,float y,float deg,float rad,float w) {
int a = int(min (deg/SINCOS_PRECISION,SINCOS_LENGTH-1));
beginShape(QUAD_STRIP);
for (int i = 0; i < a; i++) {
vertex(cosLUT[i]*(rad)+x,sinLUT[i]*(rad)+y);
vertex(cosLUT[i]*(rad+w)+x,sinLUT[i]*(rad+w)+y);
}
endShape();
}
@@ -0,0 +1,48 @@
/**
* LightsGL.
* Modified from an example by Simon Greenwold.
*
* Display a box with three different kinds of lights.
*/
import processing.opengl.*;
void setup()
{
size(1024, 768, OPENGL);
noStroke();
}
void draw()
{
defineLights();
background(0);
for (int x = 0; x <= width; x += 100) {
for (int y = 0; y <= height; y += 100) {
pushMatrix();
translate(x, y);
rotateY(map(mouseX, 0, width, 0, PI));
rotateX(map(mouseY, 0, height, 0, PI));
box(90);
popMatrix();
}
}
}
void defineLights() {
// Orange point light on the right
pointLight(150, 100, 0, // Color
200, -150, 0); // Position
// Blue directional light from the left
directionalLight(0, 102, 255, // Color
1, 0, 0); // The x-, y-, z-axis direction
// Yellow spotlight from the front
spotLight(255, 255, 109, // Color
0, 40, 200, // Position
0, -0.5, -0.5, // Direction
PI / 2, 2); // Angle, concentration
}
@@ -0,0 +1,67 @@
class Cube {
// Properties
int w, h, d;
int shiftX, shiftY, shiftZ;
// Constructor
Cube(int w, int h, int d, int shiftX, int shiftY, int shiftZ){
this.w = w;
this.h = h;
this.d = d;
this.shiftX = shiftX;
this.shiftY = shiftY;
this.shiftZ = shiftZ;
}
// Main cube drawing method, which looks
// more confusing than it really is. It's
// just a bunch of rectangles drawn for
// each cube face
void drawCube(){
beginShape(QUADS);
// Front face
vertex(-w/2 + shiftX, -h/2 + shiftY, -d/2 + shiftZ);
vertex(w + shiftX, -h/2 + shiftY, -d/2 + shiftZ);
vertex(w + shiftX, h + shiftY, -d/2 + shiftZ);
vertex(-w/2 + shiftX, h + shiftY, -d/2 + shiftZ);
// Back face
vertex(-w/2 + shiftX, -h/2 + shiftY, d + shiftZ);
vertex(w + shiftX, -h/2 + shiftY, d + shiftZ);
vertex(w + shiftX, h + shiftY, d + shiftZ);
vertex(-w/2 + shiftX, h + shiftY, d + shiftZ);
// Left face
vertex(-w/2 + shiftX, -h/2 + shiftY, -d/2 + shiftZ);
vertex(-w/2 + shiftX, -h/2 + shiftY, d + shiftZ);
vertex(-w/2 + shiftX, h + shiftY, d + shiftZ);
vertex(-w/2 + shiftX, h + shiftY, -d/2 + shiftZ);
// Right face
vertex(w + shiftX, -h/2 + shiftY, -d/2 + shiftZ);
vertex(w + shiftX, -h/2 + shiftY, d + shiftZ);
vertex(w + shiftX, h + shiftY, d + shiftZ);
vertex(w + shiftX, h + shiftY, -d/2 + shiftZ);
// Top face
vertex(-w/2 + shiftX, -h/2 + shiftY, -d/2 + shiftZ);
vertex(w + shiftX, -h/2 + shiftY, -d/2 + shiftZ);
vertex(w + shiftX, -h/2 + shiftY, d + shiftZ);
vertex(-w/2 + shiftX, -h/2 + shiftY, d + shiftZ);
// Bottom face
vertex(-w/2 + shiftX, h + shiftY, -d/2 + shiftZ);
vertex(w + shiftX, h + shiftY, -d/2 + shiftZ);
vertex(w + shiftX, h + shiftY, d + shiftZ);
vertex(-w/2 + shiftX, h + shiftY, d + shiftZ);
endShape();
// Add some rotation to each box for pizazz.
rotateY(radians(1));
rotateX(radians(1));
rotateZ(radians(1));
}
}
@@ -0,0 +1,65 @@
/**
* Space Junk
* by Ira Greenberg.
* Zoom suggestion
* by Danny Greenberg.
*
* Rotating cubes in space using a custom Cube class.
* Color controlled by light sources. Move the mouse left
* and right to zoom.
*/
import processing.opengl.*;
// Used for oveall rotation
float ang;
// Cube count-lower/raise to test P3D/OPENGL performance
int limit = 500;
// Array for all cubes
Cube[]cubes = new Cube[limit];
void setup() {
size(1024, 768, OPENGL);
background(0);
noStroke();
// Instantiate cubes, passing in random vals for size and postion
for (int i = 0; i< cubes.length; i++){
cubes[i] = new Cube(int(random(-10, 10)), int(random(-10, 10)),
int(random(-10, 10)), int(random(-140, 140)), int(random(-140, 140)),
int(random(-140, 140)));
}
}
void draw(){
background(0);
fill(200);
// Set up some different colored lights
pointLight(51, 102, 255, 65, 60, 100);
pointLight(200, 40, 60, -65, -60, -150);
// Raise overall light in scene
ambientLight(70, 70, 10);
// Center geometry in display windwow.
// you can change 3rd argument ('0')
// to move block group closer(+)/further(-)
translate(width/2, height/2, -200 + mouseX * 0.65);
// Rotate around y and x axes
rotateY(radians(ang));
rotateX(radians(ang));
// Draw cubes
for (int i = 0; i < cubes.length; i++){
cubes[i].drawCube();
}
// Used in rotate function calls above
ang++;
}
@@ -0,0 +1,174 @@
/**
* Textured Sphere
* by Mike 'Flux' Chang (cleaned up by Aaron Koblin).
* Based on code by Toxi.
*
* A 3D textured sphere with simple rotation control.
* Note: Controls will be inverted when sphere is upside down.
* Use an "arc ball" to deal with this appropriately.
*/
import processing.opengl.*;
PImage bg;
PImage texmap;
int sDetail = 35; // Sphere detail setting
float rotationX = 0;
float rotationY = 0;
float velocityX = 0;
float velocityY = 0;
float globeRadius = 450;
float pushBack = 0;
float[] cx, cz, sphereX, sphereY, sphereZ;
float sinLUT[];
float cosLUT[];
float SINCOS_PRECISION = 0.5;
int SINCOS_LENGTH = int(360.0 / SINCOS_PRECISION);
void setup() {
size(1024, 768, OPENGL);
texmap = loadImage("world32k.jpg");
initializeSphere(sDetail);
}
void draw() {
background(0);
renderGlobe();
}
void renderGlobe() {
pushMatrix();
translate(width/2.0, height/2.0, pushBack);
pushMatrix();
noFill();
stroke(255,200);
strokeWeight(2);
smooth();
popMatrix();
lights();
pushMatrix();
rotateX( radians(-rotationX) );
rotateY( radians(270 - rotationY) );
fill(200);
noStroke();
textureMode(IMAGE);
texturedSphere(globeRadius, texmap);
popMatrix();
popMatrix();
rotationX += velocityX;
rotationY += velocityY;
velocityX *= 0.95;
velocityY *= 0.95;
// Implements mouse control (interaction will be inverse when sphere is upside down)
if(mousePressed){
velocityX += (mouseY-pmouseY) * 0.01;
velocityY -= (mouseX-pmouseX) * 0.01;
}
}
void initializeSphere(int res)
{
sinLUT = new float[SINCOS_LENGTH];
cosLUT = new float[SINCOS_LENGTH];
for (int i = 0; i < SINCOS_LENGTH; i++) {
sinLUT[i] = (float) Math.sin(i * DEG_TO_RAD * SINCOS_PRECISION);
cosLUT[i] = (float) Math.cos(i * DEG_TO_RAD * SINCOS_PRECISION);
}
float delta = (float)SINCOS_LENGTH/res;
float[] cx = new float[res];
float[] cz = new float[res];
// Calc unit circle in XZ plane
for (int i = 0; i < res; i++) {
cx[i] = -cosLUT[(int) (i*delta) % SINCOS_LENGTH];
cz[i] = sinLUT[(int) (i*delta) % SINCOS_LENGTH];
}
// Computing vertexlist vertexlist starts at south pole
int vertCount = res * (res-1) + 2;
int currVert = 0;
// Re-init arrays to store vertices
sphereX = new float[vertCount];
sphereY = new float[vertCount];
sphereZ = new float[vertCount];
float angle_step = (SINCOS_LENGTH*0.5f)/res;
float angle = angle_step;
// Step along Y axis
for (int i = 1; i < res; i++) {
float curradius = sinLUT[(int) angle % SINCOS_LENGTH];
float currY = -cosLUT[(int) angle % SINCOS_LENGTH];
for (int j = 0; j < res; j++) {
sphereX[currVert] = cx[j] * curradius;
sphereY[currVert] = currY;
sphereZ[currVert++] = cz[j] * curradius;
}
angle += angle_step;
}
sDetail = res;
}
// Generic routine to draw textured sphere
void texturedSphere(float r, PImage t)
{
int v1,v11,v2;
r = (r + 240 ) * 0.33;
beginShape(TRIANGLE_STRIP);
texture(t);
float iu=(float)(t.width-1)/(sDetail);
float iv=(float)(t.height-1)/(sDetail);
float u=0,v=iv;
for (int i = 0; i < sDetail; i++) {
vertex(0, -r, 0,u,0);
vertex(sphereX[i]*r, sphereY[i]*r, sphereZ[i]*r, u, v);
u+=iu;
}
vertex(0, -r, 0,u,0);
vertex(sphereX[0]*r, sphereY[0]*r, sphereZ[0]*r, u, v);
endShape();
// Middle rings
int voff = 0;
for(int i = 2; i < sDetail; i++) {
v1=v11=voff;
voff += sDetail;
v2=voff;
u=0;
beginShape(TRIANGLE_STRIP);
texture(t);
for (int j = 0; j < sDetail; j++) {
vertex(sphereX[v1]*r, sphereY[v1]*r, sphereZ[v1++]*r, u, v);
vertex(sphereX[v2]*r, sphereY[v2]*r, sphereZ[v2++]*r, u, v+iv);
u+=iu;
}
// Close each ring
v1=v11;
v2=voff;
vertex(sphereX[v1]*r, sphereY[v1]*r, sphereZ[v1]*r, u, v);
vertex(sphereX[v2]*r, sphereY[v2]*r, sphereZ[v2]*r, u, v+iv);
endShape();
v+=iv;
}
u=0;
// Add the northern cap
beginShape(TRIANGLE_STRIP);
texture(t);
for (int i = 0; i < sDetail; i++) {
v2 = voff + i;
vertex(sphereX[v2]*r, sphereY[v2]*r, sphereZ[v2]*r, u, v);
vertex(0, r, 0,u,v+iv);
u+=iu;
}
vertex(sphereX[voff]*r, sphereY[voff]*r, sphereZ[voff]*r, u, v);
endShape();
}
@@ -0,0 +1,256 @@
class Gesture {
float damp = 5.0;
float dampInv = 1.0 / damp;
float damp1 = damp - 1;
int w;
int h;
int capacity;
Vec3f path[];
int crosses[];
Polygon polygons[];
int nPoints;
int nPolys;
float jumpDx, jumpDy;
boolean exists;
float INIT_TH = 14;
float thickness = INIT_TH;
Gesture(int mw, int mh) {
w = mw;
h = mh;
capacity = 600;
path = new Vec3f[capacity];
polygons = new Polygon[capacity];
crosses = new int[capacity];
for (int i=0;i<capacity;i++) {
polygons[i] = new Polygon();
polygons[i].npoints = 4;
path[i] = new Vec3f();
crosses[i] = 0;
}
nPoints = 0;
nPolys = 0;
exists = false;
jumpDx = 0;
jumpDy = 0;
}
void clear() {
nPoints = 0;
exists = false;
thickness = INIT_TH;
}
void clearPolys() {
nPolys = 0;
}
void addPoint(float x, float y) {
if (nPoints >= capacity) {
// there are all sorts of possible solutions here,
// but for abject simplicity, I don't do anything.
}
else {
float v = distToLast(x, y);
float p = getPressureFromVelocity(v);
path[nPoints++].set(x,y,p);
if (nPoints > 1) {
exists = true;
jumpDx = path[nPoints-1].x - path[0].x;
jumpDy = path[nPoints-1].y - path[0].y;
}
}
}
float getPressureFromVelocity(float v) {
final float scale = 18;
final float minP = 0.02;
final float oldP = (nPoints > 0) ? path[nPoints-1].p : 0;
return ((minP + max(0, 1.0 - v/scale)) + (damp1*oldP))*dampInv;
}
void setPressures() {
// pressures vary from 0...1
float pressure;
Vec3f tmp;
float t = 0;
float u = 1.0 / (nPoints - 1)*TWO_PI;
for (int i = 0; i < nPoints; i++) {
pressure = sqrt((1.0 - cos(t))*0.5);
path[i].p = pressure;
t += u;
}
}
float distToLast(float ix, float iy) {
if (nPoints > 0) {
Vec3f v = path[nPoints-1];
float dx = v.x - ix;
float dy = v.y - iy;
return mag(dx, dy);
}
else {
return 30;
}
}
void compile() {
// compute the polygons from the path of Vec3f's
if (exists) {
clearPolys();
Vec3f p0, p1, p2;
float radius0, radius1;
float ax, bx, cx, dx;
float ay, by, cy, dy;
int axi, bxi, cxi, dxi, axip, axid;
int ayi, byi, cyi, dyi, ayip, ayid;
float p1x, p1y;
float dx01, dy01, hp01, si01, co01;
float dx02, dy02, hp02, si02, co02;
float dx13, dy13, hp13, si13, co13;
float taper = 1.0;
int nPathPoints = nPoints - 1;
int lastPolyIndex = nPathPoints - 1;
float npm1finv = 1.0 / max(1, nPathPoints - 1);
// handle the first point
p0 = path[0];
p1 = path[1];
radius0 = p0.p * thickness;
dx01 = p1.x - p0.x;
dy01 = p1.y - p0.y;
hp01 = sqrt(dx01*dx01 + dy01*dy01);
if (hp01 == 0) {
hp02 = 0.0001;
}
co01 = radius0 * dx01 / hp01;
si01 = radius0 * dy01 / hp01;
ax = p0.x - si01;
ay = p0.y + co01;
bx = p0.x + si01;
by = p0.y - co01;
int xpts[];
int ypts[];
int LC = 20;
int RC = w-LC;
int TC = 20;
int BC = h-TC;
float mint = 0.618;
float tapow = 0.4;
// handle the middle points
int i = 1;
Polygon apoly;
for (i = 1; i < nPathPoints; i++) {
taper = pow((lastPolyIndex-i)*npm1finv,tapow);
p0 = path[i-1];
p1 = path[i ];
p2 = path[i+1];
p1x = p1.x;
p1y = p1.y;
radius1 = Math.max(mint,taper*p1.p*thickness);
// assumes all segments are roughly the same length...
dx02 = p2.x - p0.x;
dy02 = p2.y - p0.y;
hp02 = (float) Math.sqrt(dx02*dx02 + dy02*dy02);
if (hp02 != 0) {
hp02 = radius1/hp02;
}
co02 = dx02 * hp02;
si02 = dy02 * hp02;
// translate the integer coordinates to the viewing rectangle
axi = axip = (int)ax;
ayi = ayip = (int)ay;
axi=(axi<0)?(w-((-axi)%w)):axi%w;
axid = axi-axip;
ayi=(ayi<0)?(h-((-ayi)%h)):ayi%h;
ayid = ayi-ayip;
// set the vertices of the polygon
apoly = polygons[nPolys++];
xpts = apoly.xpoints;
ypts = apoly.ypoints;
xpts[0] = axi = axid + axip;
xpts[1] = bxi = axid + (int) bx;
xpts[2] = cxi = axid + (int)(cx = p1x + si02);
xpts[3] = dxi = axid + (int)(dx = p1x - si02);
ypts[0] = ayi = ayid + ayip;
ypts[1] = byi = ayid + (int) by;
ypts[2] = cyi = ayid + (int)(cy = p1y - co02);
ypts[3] = dyi = ayid + (int)(dy = p1y + co02);
// keep a record of where we cross the edge of the screen
crosses[i] = 0;
if ((axi<=LC)||(bxi<=LC)||(cxi<=LC)||(dxi<=LC)) {
crosses[i]|=1;
}
if ((axi>=RC)||(bxi>=RC)||(cxi>=RC)||(dxi>=RC)) {
crosses[i]|=2;
}
if ((ayi<=TC)||(byi<=TC)||(cyi<=TC)||(dyi<=TC)) {
crosses[i]|=4;
}
if ((ayi>=BC)||(byi>=BC)||(cyi>=BC)||(dyi>=BC)) {
crosses[i]|=8;
}
//swap data for next time
ax = dx;
ay = dy;
bx = cx;
by = cy;
}
// handle the last point
p2 = path[nPathPoints];
apoly = polygons[nPolys++];
xpts = apoly.xpoints;
ypts = apoly.ypoints;
xpts[0] = (int)ax;
xpts[1] = (int)bx;
xpts[2] = (int)(p2.x);
xpts[3] = (int)(p2.x);
ypts[0] = (int)ay;
ypts[1] = (int)by;
ypts[2] = (int)(p2.y);
ypts[3] = (int)(p2.y);
}
}
void smooth() {
// average neighboring points
final float weight = 18;
final float scale = 1.0 / (weight + 2);
int nPointsMinusTwo = nPoints - 2;
Vec3f lower, upper, center;
for (int i = 1; i < nPointsMinusTwo; i++) {
lower = path[i-1];
center = path[i];
upper = path[i+1];
center.x = (lower.x + weight*center.x + upper.x)*scale;
center.y = (lower.y + weight*center.y + upper.y)*scale;
}
}
}
@@ -0,0 +1,19 @@
class Vec3f {
float x;
float y;
float p; // Pressure
Vec3f() {
set(0, 0, 0);
}
Vec3f(float ix, float iy, float ip) {
set(ix, iy, ip);
}
void set(float ix, float iy, float ip) {
x = ix;
y = iy;
p = ip;
}
}
@@ -0,0 +1,190 @@
/**
* Yellowtail
* by Golan Levin (www.flong.com).
*
* Click, drag, and release to create a kinetic gesture.
*
* Yellowtail (1998-2000) is an interactive software system for the gestural
* creation and performance of real-time abstract animation. Yellowtail repeats
* a user's strokes end-over-end, enabling simultaneous specification of a
* line's shape and quality of movement. Each line repeats according to its
* own period, producing an ever-changing and responsive display of lively,
* worm-like textures.
*/
import processing.opengl.*;
import java.awt.Polygon;
Gesture gestureArray[];
final int nGestures = 36; // Number of gestures
final int minMove = 3; // Minimum travel for a new point
int currentGestureID;
Polygon tempP;
int tmpXp[];
int tmpYp[];
void setup() {
size(1024, 768, OPENGL);
background(0, 0, 0);
noStroke();
currentGestureID = -1;
gestureArray = new Gesture[nGestures];
for (int i = 0; i < nGestures; i++) {
gestureArray[i] = new Gesture(width, height);
}
clearGestures();
}
void draw() {
background(0);
updateGeometry();
fill(255, 255, 245);
for (int i = 0; i < nGestures; i++) {
renderGesture(gestureArray[i], width, height);
}
}
void mousePressed() {
currentGestureID = (currentGestureID+1) % nGestures;
Gesture G = gestureArray[currentGestureID];
G.clear();
G.clearPolys();
G.addPoint(mouseX, mouseY);
}
void mouseDragged() {
if (currentGestureID >= 0) {
Gesture G = gestureArray[currentGestureID];
if (G.distToLast(mouseX, mouseY) > minMove) {
G.addPoint(mouseX, mouseY);
G.smooth();
G.compile();
}
}
}
void keyPressed() {
if (key == '+' || key == '=') {
if (currentGestureID >= 0) {
float th = gestureArray[currentGestureID].thickness;
gestureArray[currentGestureID].thickness = min(96, th+1);
gestureArray[currentGestureID].compile();
}
} else if (key == '-') {
if (currentGestureID >= 0) {
float th = gestureArray[currentGestureID].thickness;
gestureArray[currentGestureID].thickness = max(2, th-1);
gestureArray[currentGestureID].compile();
}
} else if (key == ' ') {
clearGestures();
}
}
void renderGesture(Gesture gesture, int w, int h) {
if (gesture.exists) {
if (gesture.nPolys > 0) {
Polygon polygons[] = gesture.polygons;
int crosses[] = gesture.crosses;
int xpts[];
int ypts[];
Polygon p;
int cr;
beginShape(QUADS);
int gnp = gesture.nPolys;
for (int i=0; i<gnp; i++) {
p = polygons[i];
xpts = p.xpoints;
ypts = p.ypoints;
vertex(xpts[0], ypts[0]);
vertex(xpts[1], ypts[1]);
vertex(xpts[2], ypts[2]);
vertex(xpts[3], ypts[3]);
if ((cr = crosses[i]) > 0) {
if ((cr & 3)>0) {
vertex(xpts[0]+w, ypts[0]);
vertex(xpts[1]+w, ypts[1]);
vertex(xpts[2]+w, ypts[2]);
vertex(xpts[3]+w, ypts[3]);
vertex(xpts[0]-w, ypts[0]);
vertex(xpts[1]-w, ypts[1]);
vertex(xpts[2]-w, ypts[2]);
vertex(xpts[3]-w, ypts[3]);
}
if ((cr & 12)>0) {
vertex(xpts[0], ypts[0]+h);
vertex(xpts[1], ypts[1]+h);
vertex(xpts[2], ypts[2]+h);
vertex(xpts[3], ypts[3]+h);
vertex(xpts[0], ypts[0]-h);
vertex(xpts[1], ypts[1]-h);
vertex(xpts[2], ypts[2]-h);
vertex(xpts[3], ypts[3]-h);
}
// I have knowingly retained the small flaw of not
// completely dealing with the corner conditions
// (the case in which both of the above are true).
}
}
endShape();
}
}
}
void updateGeometry() {
Gesture J;
for (int g=0; g<nGestures; g++) {
if ((J=gestureArray[g]).exists) {
if (g!=currentGestureID) {
advanceGesture(J);
} else if (!mousePressed) {
advanceGesture(J);
}
}
}
}
void advanceGesture(Gesture gesture) {
// Move a Gesture one step
if (gesture.exists) { // check
int nPts = gesture.nPoints;
int nPts1 = nPts-1;
Vec3f path[];
float jx = gesture.jumpDx;
float jy = gesture.jumpDy;
if (nPts > 0) {
path = gesture.path;
for (int i = nPts1; i > 0; i--) {
path[i].x = path[i-1].x;
path[i].y = path[i-1].y;
}
path[0].x = path[nPts1].x - jx;
path[0].y = path[nPts1].y - jy;
gesture.compile();
}
}
}
void clearGestures() {
for (int i = 0; i < nGestures; i++) {
gestureArray[i].clear();
}
}
@@ -0,0 +1,194 @@
/**
* PDF Complex
* by Marius Watz (workshop.evolutionzone.com).
*
* Example using PDF to output complex 3D geometry for print.
* Press "s" to save a PDF.
*/
import processing.opengl.*;
import processing.pdf.*;
// Trig lookup tables borrowed from Toxi. Cryptic but effective
float sinLUT[];
float cosLUT[];
float SINCOS_PRECISION=1.0;
int SINCOS_LENGTH= int((360.0/SINCOS_PRECISION));
// System data
boolean dosave=false;
int num;
float pt[];
int style[];
void setup() {
size(600, 600, OPENGL);
frameRate(24);
background(255);
// Fill the tables
sinLUT=new float[SINCOS_LENGTH];
cosLUT=new float[SINCOS_LENGTH];
for (int i = 0; i < SINCOS_LENGTH; i++) {
sinLUT[i]= (float)Math.sin(i*DEG_TO_RAD*SINCOS_PRECISION);
cosLUT[i]= (float)Math.cos(i*DEG_TO_RAD*SINCOS_PRECISION);
}
num = 150;
pt = new float[6*num]; // rotx, roty, deg, rad, w, speed
style = new int[2*num]; // color, render style
// Set up arc shapes
int index=0;
float prob;
for (int i=0; i<num; i++) {
pt[index++] = random(PI*2); // Random X axis rotation
pt[index++] = random(PI*2); // Random Y axis rotation
pt[index++] = random(60,80); // Short to quarter-circle arcs
if(random(100)>90) pt[index]=(int)random(8,27)*10;
pt[index++] = int(random(2,50)*5); // Radius. Space them out nicely
pt[index++] = random(4,32); // Width of band
if(random(100)>90) pt[index]=random(40,60); // Width of band
pt[index++] = radians(random(5,30))/5; // Speed of rotation
// get colors
prob = random(100);
if(prob<30) style[i*2]=colorBlended(random(1), 255,0,100, 255,0,0, 210);
else if(prob<70) style[i*2]=colorBlended(random(1), 0,153,255, 170,225,255, 210);
else if(prob<90) style[i*2]=colorBlended(random(1), 200,255,0, 150,255,0, 210);
else style[i*2]=color(255,255,255, 220);
if(prob<50) style[i*2]=colorBlended(random(1), 200,255,0, 50,120,0, 210);
else if(prob<90) style[i*2]=colorBlended(random(1), 255,100,0, 255,255,0, 210);
else style[i*2]=color(255,255,255, 220);
style[i*2+1]=(int)(random(100))%3;
}
}
void draw() {
if(dosave) {
// set up PGraphicsPDF for use with beginRaw()
PGraphicsPDF pdf = (PGraphicsPDF)beginRaw(PDF, "pdf_complex_out.pdf");
// set default Illustrator stroke styles and paint background rect.
pdf.strokeJoin(MITER);
pdf.strokeCap(SQUARE);
pdf.fill(0);
pdf.noStroke();
pdf.rect(0,0, width,height);
}
background(0);
int index=0;
translate(width/2,height/2,0);
rotateX(PI/6);
rotateY(PI/6);
for (int i=0; i<num; i++) {
pushMatrix();
rotateX(pt[index++]);
rotateY(pt[index++]);
if(style[i*2+1]==0) {
stroke(style[i*2]);
noFill();
strokeWeight(1);
arcLine(0,0, pt[index++],pt[index++],pt[index++]);
}
else if(style[i*2+1]==1) {
fill(style[i*2]);
noStroke();
arcLineBars(0,0, pt[index++],pt[index++],pt[index++]);
}
else {
fill(style[i*2]);
noStroke();
arc(0,0, pt[index++],pt[index++],pt[index++]);
}
// increase rotation
pt[index-5]+=pt[index]/10;
pt[index-4]+=pt[index++]/20;
popMatrix();
}
if(dosave) {
endRaw();
dosave=false;
}
}
// Get blend of two colors
public int colorBlended(float fract,
float r, float g, float b,
float r2, float g2, float b2, float a) {
r2 = (r2 - r);
g2 = (g2 - g);
b2 = (b2 - b);
return color(r + r2 * fract, g + g2 * fract, b + b2 * fract, a);
}
// Draw arc line
public void arcLine(float x,float y,float deg,float rad,float w) {
int a=(int)(min (deg/SINCOS_PRECISION,SINCOS_LENGTH-1));
int numlines=(int)(w/2);
for (int j=0; j<numlines; j++) {
beginShape();
for (int i=0; i<a; i++) {
vertex(cosLUT[i]*rad+x,sinLUT[i]*rad+y);
}
endShape();
rad += 2;
}
}
// Draw arc line with bars
public void arcLineBars(float x,float y,float deg,float rad,float w) {
int a = int((min (deg/SINCOS_PRECISION,SINCOS_LENGTH-1)));
a /= 4;
beginShape(QUADS);
for (int i=0; i<a; i+=4) {
vertex(cosLUT[i]*(rad)+x,sinLUT[i]*(rad)+y);
vertex(cosLUT[i]*(rad+w)+x,sinLUT[i]*(rad+w)+y);
vertex(cosLUT[i+2]*(rad+w)+x,sinLUT[i+2]*(rad+w)+y);
vertex(cosLUT[i+2]*(rad)+x,sinLUT[i+2]*(rad)+y);
}
endShape();
}
// Draw solid arc
public void arc(float x,float y,float deg,float rad,float w) {
int a = int(min (deg/SINCOS_PRECISION,SINCOS_LENGTH-1));
beginShape(QUAD_STRIP);
for (int i = 0; i < a; i++) {
vertex(cosLUT[i]*(rad)+x,sinLUT[i]*(rad)+y);
vertex(cosLUT[i]*(rad+w)+x,sinLUT[i]*(rad+w)+y);
}
endShape();
}
void keyPressed() {
if (key == 's') {
dosave=true;
}
}
void mouseReleased() {
background(255);
}
@@ -0,0 +1,30 @@
/**
* Large Page.
*
* Saves one frame as a PDF with a size larger
* than the screen. When PDF is used as the renderer
* (the third parameter of size) the display window
* does not open. The file is saved to the sketch folder.
*/
import processing.pdf.*;
void setup()
{
size(2000, 2000, PDF, "Line.pdf");
}
void draw()
{
background(255);
stroke(0, 20);
strokeWeight(20.0);
line(200, 0, width/2, height);
exit(); // Quit the program
}
@@ -0,0 +1,38 @@
/**
* Many PDFs.
*
* Saves one PDF file each each frame while the mouse is pressed.
* When the mouse is released, the PDF creation stops.
*/
import processing.pdf.*;
boolean savePDF = false;
void setup() {
size(600, 600);
frameRate(24);
}
void draw() {
if(savePDF == true) {
beginRecord(PDF, "lines" + frameCount + ".pdf");
}
background(255);
stroke(0, 20);
strokeWeight(20.0);
line(mouseX, 0, width-mouseY, height);
if(savePDF == true) {
endRecord();
}
}
void mousePressed() {
savePDF = true;
}
void mouseReleased() {
savePDF = false;
}
@@ -0,0 +1,31 @@
/**
* Many Pages.
*
* Saves a new page into a PDF file each loop through draw().
* Pressing the mouse finishes writing the file and exits the program.
*/
import processing.pdf.*;
PGraphicsPDF pdf;
void setup() {
size(600, 600);
frameRate(4);
pdf = (PGraphicsPDF)beginRecord(PDF, "Lines.pdf");
beginRecord(pdf);
}
void draw() {
background(255);
stroke(0, 20);
strokeWeight(20.0);
line(mouseX, 0, width-mouseY, height);
pdf.nextPage();
}
void mousePressed() {
endRecord();
exit();
}
@@ -0,0 +1,37 @@
/**
* Mouse Press.
*
* Saves one PDF of the contents of the display window
* each time the mouse is pressed.
*/
import processing.pdf.*;
boolean saveOneFrame = false;
void setup() {
size(600, 600);
frameRate(24);
}
void draw() {
if(saveOneFrame == true) {
beginRecord(PDF, "Line.pdf");
}
background(255);
stroke(0, 20);
strokeWeight(20.0);
line(mouseX, 0, width-mouseY, height);
if(saveOneFrame == true) {
endRecord();
saveOneFrame = false;
}
}
void mousePressed() {
saveOneFrame = true;
}
@@ -0,0 +1,33 @@
/**
* Multiple Frames.
*
* Saves one PDF document of many frames drawn to the screen.
* Starts the file when the mouse is pressed and end the file
* when the mouse is released.
*/
import processing.pdf.*;
void setup() {
size(600, 600);
frameRate(24);
background(255);
}
void draw() {
stroke(0, 20);
strokeWeight(20.0);
line(mouseX, 0, width-mouseY, height);
}
void mousePressed() {
beginRecord(PDF, "Lines.pdf");
background(255);
}
void mouseReleased() {
endRecord();
background(255);
}
@@ -0,0 +1,23 @@
/**
* One Frame.
*
* Saves one PDF with the contents of the display window.
* Because this example uses beginRecord, the image is shown
* on the display window and is saved to the file.
*/
import processing.pdf.*;
size(600, 600);
beginRecord(PDF, "line.pdf");
background(255);
stroke(0, 20);
strokeWeight(20.0);
line(200, 0, 400, height);
endRecord();
@@ -0,0 +1,45 @@
/**
* RandomBook
*
* Creates a 768 page book of random lines.
*/
import processing.pdf.*;
PGraphicsPDF pdf;
void setup() {
size(594, 842);
// randomSeed(0); // Uncomment to make the same book each time
pdf = (PGraphicsPDF)beginRecord(PDF, "RandomBook.pdf");
beginRecord(pdf);
}
void draw() {
background(255);
for (int i=0; i<100; i++) {
float r = random(1.0);
if(r < 0.2) {
stroke(255);
} else {
stroke(0);
}
float sw = pow(random(1.0), 12);
strokeWeight(sw * 260);
float x1 = random(-200, -100);
float x2 = random(width+100, width+200);
float y1 = random(-100, height+100);
float y2 = random(-100, height+100);
line(x1, y1, x2, y2);
}
if(frameCount == 768) {
endRecord();
exit(); // Quit
} else {
pdf.nextPage(); // Tell it to go to the next page
}
}
@@ -0,0 +1,150 @@
/**
* Serial Call-Response
* by Tom Igoe.
*
* Sends a byte out the serial port, and reads 3 bytes in.
* Sets foregound color, xpos, and ypos of a circle onstage
* using the values returned from the serial port.
* Thanks to Daniel Shiffman and Greg Shakar for the improvements.
*
* Note: This sketch assumes that the device on the other end of the serial
* port is going to send a single byte of value 65 (ASCII A) on startup.
* The sketch waits for that byte, then sends an ASCII A whenever
* it wants more data.
*/
import processing.serial.*;
int bgcolor; // Background color
int fgcolor; // Fill color
Serial myPort; // The serial port
int[] serialInArray = new int[3]; // Where we'll put what we receive
int serialCount = 0; // A count of how many bytes we receive
int xpos, ypos; // Starting position of the ball
boolean firstContact = false; // Whether we've heard from the microcontroller
void setup() {
size(256, 256); // Stage size
noStroke(); // No border on the next thing drawn
// Set the starting position of the ball (middle of the stage)
xpos = width/2;
ypos = height/2;
// Print a list of the serial ports, for debugging purposes:
println(Serial.list());
// I know that the first port in the serial list on my mac
// is always my FTDI adaptor, so I open Serial.list()[0].
// On Windows machines, this generally opens COM1.
// Open whatever port is the one you're using.
String portName = Serial.list()[0];
myPort = new Serial(this, portName, 9600);
}
void draw() {
background(bgcolor);
fill(fgcolor);
// Draw the shape
ellipse(xpos, ypos, 20, 20);
}
void serialEvent(Serial myPort) {
// read a byte from the serial port:
int inByte = myPort.read();
// if this is the first byte received, and it's an A,
// clear the serial buffer and note that you've
// had first contact from the microcontroller.
// Otherwise, add the incoming byte to the array:
if (firstContact == false) {
if (inByte == 'A') {
myPort.clear(); // clear the serial port buffer
firstContact = true; // you've had first contact from the microcontroller
myPort.write('A'); // ask for more
}
}
else {
// Add the latest byte from the serial port to array:
serialInArray[serialCount] = inByte;
serialCount++;
// If we have 3 bytes:
if (serialCount > 2 ) {
xpos = serialInArray[0];
ypos = serialInArray[1];
fgcolor = serialInArray[2];
// print the values (for debugging purposes only):
println(xpos + "\t" + ypos + "\t" + fgcolor);
// Send a capital A to request new sensor readings:
myPort.write('A');
// Reset serialCount:
serialCount = 0;
}
}
}
/*
// Serial Call and Response
// by Tom Igoe
// Language: Wiring/Arduino
// This program sends an ASCII A (byte of value 65) on startup
// and repeats that until it gets some data in.
// Then it waits for a byte in the serial port, and
// sends three sensor values whenever it gets a byte in.
// Thanks to Greg Shakar for the improvements
// Created 26 Sept. 2005
// Updated 18 April 2008
int firstSensor = 0; // first analog sensor
int secondSensor = 0; // second analog sensor
int thirdSensor = 0; // digital sensor
int inByte = 0; // incoming serial byte
void setup()
{
// start serial port at 9600 bps:
Serial.begin(9600);
pinMode(2, INPUT); // digital sensor is on digital pin 2
establishContact(); // send a byte to establish contact until Processing responds
}
void loop()
{
// if we get a valid byte, read analog ins:
if (Serial.available() > 0) {
// get incoming byte:
inByte = Serial.read();
// read first analog input, divide by 4 to make the range 0-255:
firstSensor = analogRead(0)/4;
// delay 10ms to let the ADC recover:
delay(10);
// read second analog input, divide by 4 to make the range 0-255:
secondSensor = analogRead(1)/4;
// read switch, multiply by 155 and add 100
// so that you're sending 100 or 255:
thirdSensor = 100 + (155 * digitalRead(2));
// send sensor values:
Serial.print(firstSensor, BYTE);
Serial.print(secondSensor, BYTE);
Serial.print(thirdSensor, BYTE);
}
}
void establishContact() {
while (Serial.available() <= 0) {
Serial.print('A', BYTE); // send a capital A
delay(300);
}
}
*/
@@ -0,0 +1,50 @@
/**
* Serial Duplex
* by Tom Igoe.
*
* Sends a byte out the serial port when you type a key
* listens for bytes received, and displays their value.
* This is just a quick application for testing serial data
* in both directions.
*/
import processing.serial.*;
Serial myPort; // The serial port
int whichKey = -1; // Variable to hold keystoke values
int inByte = -1; // Incoming serial data
void setup() {
size(400, 300);
// create a font with the third font available to the system:
PFont myFont = createFont(PFont.list()[2], 14);
textFont(myFont);
// List all the available serial ports:
println(Serial.list());
// I know that the first port in the serial list on my mac
// is always my FTDI adaptor, so I open Serial.list()[0].
// In Windows, this usually opens COM1.
// Open whatever port is the one you're using.
String portName = Serial.list()[0];
myPort = new Serial(this, portName, 9600);
}
void draw() {
background(0);
text("Last Received: " + inByte, 10, 130);
text("Last Sent: " + whichKey, 10, 100);
}
void serialEvent(Serial myPort) {
inByte = myPort.read();
}
void keyPressed() {
// Send the keystroke out:
myPort.write(key);
whichKey = key;
}
@@ -0,0 +1,86 @@
/**
* Many Serial Ports
*
* Read data from the multiple Serial Ports
*/
import processing.serial.*;
Serial[] myPorts = new Serial[2]; // Create a list of objects from Serial class
int[] dataIn = new int[2]; // a list to hold data from the serial ports
void setup() {
size(400, 300);
// print a list of the serial ports:
println(Serial.list());
// On my machine, the first and third ports in the list
// were the serial ports that my microcontrollers were
// attached to.
// Open whatever ports ares the ones you're using.
// get the ports' names:
String portOne = Serial.list()[0];
String portTwo = Serial.list()[2];
// open the ports:
myPorts[0] = new Serial(this, portOne, 9600);
myPorts[1] = new Serial(this, portTwo, 9600);
}
void draw() {
// clear the screen:
background(0);
// use the latest byte from port 0 for the first circle
fill(dataIn[0]);
ellipse(width/3, height/2, 40, 40);
// use the latest byte from port 1 for the second circle
fill(dataIn[1]);
ellipse(2*width/3, height/2, 40, 40);
}
/**
* When SerialEvent is generated, it'll also give you
* the port that generated it. Check that against a list
* of the ports you know you opened to find out where
* the data came from
*/
void serialEvent(Serial thisPort) {
// variable to hold the number of the port:
int portNumber = -1;
// iterate over the list of ports opened, and match the
// one that generated this event:
for (int p = 0; p < myPorts.length; p++) {
if (thisPort == myPorts[p]) {
portNumber = p;
}
}
// read a byte from the port:
int inByte = thisPort.read();
// put it in the list that holds the latest data from each port:
dataIn[portNumber] = inByte;
// tell us who sent what:
println("Got " + inByte + " from serial port " + portNumber);
}
/*
The following Wiring/Arduino code runs on both microcontrollers that
were used to send data to this sketch:
void setup()
{
// start serial port at 9600 bps:
Serial.begin(9600);
}
void loop() {
// read analog input, divide by 4 to make the range 0-255:
int analogValue = analogRead(0)/4;
Serial.print(analogValue, BYTE);
// pause for 10 milliseconds:
delay(10);
}
*/
@@ -0,0 +1,64 @@
/**
* Simple Read
*
* Read data from the serial port and change the color of a rectangle
* when a switch connected to a Wiring or Arduino board is pressed and released.
* This example works with the Wiring / Arduino program that follows below.
*/
import processing.serial.*;
Serial myPort; // Create object from Serial class
int val; // Data received from the serial port
void setup()
{
size(200, 200);
// I know that the first port in the serial list on my mac
// is always my FTDI adaptor, so I open Serial.list()[0].
// On Windows machines, this generally opens COM1.
// Open whatever port is the one you're using.
String portName = Serial.list()[0];
myPort = new Serial(this, portName, 9600);
}
void draw()
{
if ( myPort.available() > 0) { // If data is available,
val = myPort.read(); // read it and store it in val
}
background(255); // Set background to white
if (val == 0) { // If the serial value is 0,
fill(0); // set fill to black
}
else { // If the serial value is not 0,
fill(204); // set fill to light gray
}
rect(50, 50, 100, 100);
}
/*
// Wiring / Arduino Code
// Code for sensing a switch status and writing the value to the serial port.
int switchPin = 4; // Switch connected to pin 4
void setup() {
pinMode(switchPin, INPUT); // Set pin 0 as an input
Serial.begin(9600); // Start serial communication at 9600 bps
}
void loop() {
if (digitalRead(switchPin) == HIGH) { // If switch is ON,
Serial.print(1, BYTE); // send 1 to Processing
} else { // If the switch is not ON,
Serial.print(0, BYTE); // send 0 to Processing
}
delay(100); // Wait 100 milliseconds
}
*/
@@ -0,0 +1,67 @@
/**
* Simple Write.
*
* Check if the mouse is over a rectangle and writes the status to the serial port.
* This example works with the Wiring / Arduino program that follows below.
*/
import processing.serial.*;
Serial myPort; // Create object from Serial class
int val; // Data received from the serial port
void setup()
{
size(200, 200);
// I know that the first port in the serial list on my mac
// is always my FTDI adaptor, so I open Serial.list()[0].
// On Windows machines, this generally opens COM1.
// Open whatever port is the one you're using.
String portName = Serial.list()[0];
myPort = new Serial(this, portName, 9600);
}
void draw() {
background(255);
if (mouseOverRect() == true) { // If mouse is over square,
fill(204); // change color and
myPort.write('H'); // send an H to indicate mouse is over square
}
else { // If mouse is not over square,
fill(0); // change color and
myPort.write('L'); // send an L otherwise
}
rect(50, 50, 100, 100); // Draw a square
}
boolean mouseOverRect() { // Test if mouse is over square
return ((mouseX >= 50) && (mouseX <= 150) && (mouseY >= 50) && (mouseY <= 150));
}
/*
// Wiring/Arduino code:
// Read data from the serial and turn ON or OFF a light depending on the value
char val; // Data received from the serial port
int ledPin = 4; // Set the pin to digital I/O 4
void setup() {
pinMode(ledPin, OUTPUT); // Set pin as OUTPUT
Serial.begin(9600); // Start serial communication at 9600 bps
}
void loop() {
if (Serial.available()) { // If data is available to read,
val = Serial.read(); // read it and store it in val
}
if (val == 'H') { // If H was received
digitalWrite(ledPin, HIGH); // turn the LED on
} else {
digitalWrite(ledPin, LOW); // Otherwise turn it OFF
}
delay(100); // Wait 100 milliseconds for next reading
}
*/
@@ -0,0 +1,134 @@
/**
* ASCII Video
* by Ben Fry.
*
* Text characters have been used to represent images since the earliest computers.
* This sketch is a simple homage that re-interprets live video as ASCII text.
* See the keyPressed function for more options, like changing the font size.
*/
import processing.video.*;
Capture video;
boolean cheatScreen;
// All ASCII characters, sorted according to their visual density
String letterOrder =
" .`-_':,;^=+/\"|)\\<>)iv%xclrs{*}I?!][1taeo7zjLu" +
"nT#JCwfy325Fp6mqSghVd4EgXPGZbYkOA&8U$@KHDBWNMR0Q";
char[] letters;
float[] bright;
char[] chars;
PFont font;
float fontSize = 1.5;
public void setup() {
size(640, 480, P2D);
// Or run full screen, more fun! Use with Sketch -> Present
//size(screen.width, screen.height, OPENGL);
// Uses the default video input, see the reference if this causes an error
video = new Capture(this, 80, 60, 15);
int count = video.width * video.height;
font = loadFont("UniversLTStd-Light-48.vlw");
// for the 256 levels of brightness, distribute the letters across
// the an array of 256 elements to use for the lookup
letters = new char[256];
for (int i = 0; i < 256; i++) {
int index = int(map(i, 0, 256, 0, letterOrder.length()));
letters[i] = letterOrder.charAt(index);
}
// current characters for each position in the video
chars = new char[count];
// current brightness for each point
bright = new float[count];
for (int i = 0; i < count; i++) {
// set each brightness at the midpoint to start
bright[i] = 128;
}
}
public void captureEvent(Capture c) {
c.read();
}
void draw() {
background(0);
pushMatrix();
float hgap = width / float(video.width);
float vgap = height / float(video.height);
scale(max(hgap, vgap) * fontSize);
textFont(font, fontSize);
int index = 0;
for (int y = 1; y < video.height; y++) {
// Move down for next line
translate(0, 1.0 / fontSize);
pushMatrix();
for (int x = 0; x < video.width; x++) {
int pixelColor = video.pixels[index];
// Faster method of calculating r, g, b than red(), green(), blue()
int r = (pixelColor >> 16) & 0xff;
int g = (pixelColor >> 8) & 0xff;
int b = pixelColor & 0xff;
// Another option would be to properly calculate brightness as luminance:
// luminance = 0.3*red + 0.59*green + 0.11*blue
// Or you could instead red + green + blue, and make the the values[] array
// 256*3 elements long instead of just 256.
int pixelBright = max(r, g, b);
// The 0.1 value is used to damp the changes so that letters flicker less
float diff = pixelBright - bright[index];
bright[index] += diff * 0.1;
fill(pixelColor);
int num = int(bright[index]);
text(letters[num], 0, 0);
// Move to the next pixel
index++;
// Move over for next character
translate(1.0 / fontSize, 0);
}
popMatrix();
}
popMatrix();
if (cheatScreen) {
//image(video, 0, height - video.height);
// set() is faster than image() when drawing untransformed images
set(0, height - video.height, video);
}
}
/**
* Handle key presses:
* 'c' toggles the cheat screen that shows the original image in the corner
* 'g' grabs an image and saves the frame to a tiff image
* 'f' and 'F' increase and decrease the font size
*/
public void keyPressed() {
switch (key) {
case 'g': saveFrame(); break;
case 'c': cheatScreen = !cheatScreen; break;
case 'f': fontSize *= 1.1; break;
case 'F': fontSize *= 0.9; break;
}
}
@@ -0,0 +1,69 @@
/**
* Background Subtraction
* by Golan Levin.
*
* Detect the presence of people and objects in the frame using a simple
* background-subtraction technique. To initialize the background, press a key.
*/
import processing.video.*;
int numPixels;
int[] backgroundPixels;
Capture video;
void setup() {
// Change size to 320 x 240 if too slow at 640 x 480
size(640, 480, P2D);
video = new Capture(this, width, height, 24);
numPixels = video.width * video.height;
// Create array to store the background image
backgroundPixels = new int[numPixels];
// Make the pixels[] array available for direct manipulation
loadPixels();
}
void draw() {
if (video.available()) {
video.read(); // Read a new video frame
video.loadPixels(); // Make the pixels of video available
// Difference between the current frame and the stored background
int presenceSum = 0;
for (int i = 0; i < numPixels; i++) { // For each pixel in the video frame...
// Fetch the current color in that location, and also the color
// of the background in that spot
color currColor = video.pixels[i];
color bkgdColor = backgroundPixels[i];
// Extract the red, green, and blue components of the current pixels color
int currR = (currColor >> 16) & 0xFF;
int currG = (currColor >> 8) & 0xFF;
int currB = currColor & 0xFF;
// Extract the red, green, and blue components of the background pixels color
int bkgdR = (bkgdColor >> 16) & 0xFF;
int bkgdG = (bkgdColor >> 8) & 0xFF;
int bkgdB = bkgdColor & 0xFF;
// Compute the difference of the red, green, and blue values
int diffR = abs(currR - bkgdR);
int diffG = abs(currG - bkgdG);
int diffB = abs(currB - bkgdB);
// Add these differences to the running tally
presenceSum += diffR + diffG + diffB;
// Render the difference image to the screen
//pixels[i] = color(diffR, diffG, diffB);
// The following line does the same thing much faster, but is more technical
pixels[i] = 0xFF000000 | (diffR << 16) | (diffG << 8) | diffB;
}
updatePixels(); // Notify that the pixels[] array has changed
println(presenceSum); // Print out the total amount of movement
}
}
// When a key is pressed, capture the background image into the backgroundPixels
// buffer, by copying each of the current frames pixels into it.
void keyPressed() {
video.loadPixels();
arraycopy(video.pixels, backgroundPixels);
}
@@ -0,0 +1,57 @@
/**
* Brightness Thresholding
* by Golan Levin.
*
* Determines whether a test location (such as the cursor) is contained within
* the silhouette of a dark object.
*/
import processing.video.*;
color black = color(0);
color white = color(255);
int numPixels;
Capture video;
void setup() {
size(640, 480); // Change size to 320 x 240 if too slow at 640 x 480
strokeWeight(5);
// Uses the default video input, see the reference if this causes an error
video = new Capture(this, width, height, 24);
numPixels = video.width * video.height;
noCursor();
smooth();
}
void draw() {
if (video.available()) {
video.read();
video.loadPixels();
int threshold = 127; // Set the threshold value
float pixelBrightness; // Declare variable to store a pixel's color
// Turn each pixel in the video frame black or white depending on its brightness
loadPixels();
for (int i = 0; i < numPixels; i++) {
pixelBrightness = brightness(video.pixels[i]);
if (pixelBrightness > threshold) { // If the pixel is brighter than the
pixels[i] = white; // threshold value, make it white
}
else { // Otherwise,
pixels[i] = black; // make it black
}
}
updatePixels();
// Test a location to see where it is contained. Fetch the pixel at the test
// location (the cursor), and compute its brightness
int testValue = get(mouseX, mouseY);
float testBrightness = brightness(testValue);
if (testBrightness > threshold) { // If the test location is brighter than
fill(black); // the threshold set the fill to black
}
else { // Otherwise,
fill(white); // set the fill to white
}
ellipse(mouseX, mouseY, 20, 20);
}
}
@@ -0,0 +1,52 @@
/**
* Brightness Tracking
* by Golan Levin.
*
* Tracks the brightest pixel in a live video signal.
*/
import processing.video.*;
Capture video;
void setup() {
size(640, 480); // Change size to 320 x 240 if too slow at 640 x 480
// Uses the default video input, see the reference if this causes an error
video = new Capture(this, width, height, 30);
noStroke();
smooth();
}
void draw() {
if (video.available()) {
video.read();
image(video, 0, 0, width, height); // Draw the webcam video onto the screen
int brightestX = 0; // X-coordinate of the brightest video pixel
int brightestY = 0; // Y-coordinate of the brightest video pixel
float brightestValue = 0; // Brightness of the brightest video pixel
// Search for the brightest pixel: For each row of pixels in the video image and
// for each pixel in the yth row, compute each pixel's index in the video
video.loadPixels();
int index = 0;
for (int y = 0; y < video.height; y++) {
for (int x = 0; x < video.width; x++) {
// Get the color stored in the pixel
int pixelValue = video.pixels[index];
// Determine the brightness of the pixel
float pixelBrightness = brightness(pixelValue);
// If that value is brighter than any previous, then store the
// brightness of that pixel, as well as its (x,y) location
if (pixelBrightness > brightestValue) {
brightestValue = pixelBrightness;
brightestY = y;
brightestX = x;
}
index++;
}
}
// Draw a large, yellow circle at the brightest pixel
fill(255, 204, 0, 128);
ellipse(brightestX, brightestY, 200, 200);
}
}
@@ -0,0 +1,145 @@
/**
* Color Sorting
* by Ben Fry.
*
* Example that sorts all colors from the incoming video
* and arranges them into vertical bars.
*/
import processing.video.*;
Capture video;
boolean cheatScreen;
Tuple[] captureColors;
Tuple[] drawColors;
int[] bright;
// How many pixels to skip in either direction
int increment = 5;
void setup() {
size(800, 600, P3D);
noCursor();
// Uses the default video input, see the reference if this causes an error
video = new Capture(this, 80, 60, 15);
int count = (video.width * video.height) / (increment * increment);
bright = new int[count];
captureColors = new Tuple[count];
drawColors = new Tuple[count];
for (int i = 0; i < count; i++) {
captureColors[i] = new Tuple();
drawColors[i] = new Tuple(0.5, 0.5, 0.5);
}
}
void draw() {
if (video.available()) {
video.read();
background(0);
noStroke();
int index = 0;
for (int j = 0; j < video.height; j += increment) {
for (int i = 0; i < video.width; i += increment) {
int pixelColor = video.pixels[j*video.width + i];
int r = (pixelColor >> 16) & 0xff;
int g = (pixelColor >> 8) & 0xff;
int b = pixelColor & 0xff;
// Technically would be sqrt of the following, but no need to do
// sqrt before comparing the elements since we're only ordering
bright[index] = r*r + g*g + b*b;
captureColors[index].set(r, g, b);
index++;
}
}
sort(index, bright, captureColors);
beginShape(QUAD_STRIP);
for (int i = 0; i < index; i++) {
drawColors[i].target(captureColors[i], 0.1);
drawColors[i].phil();
float x = map(i, 0, index, 0, width);
vertex(x, 0);
vertex(x, height);
}
endShape();
if (cheatScreen) {
//image(video, 0, height - video.height);
// Faster method of displaying pixels array on screen
set(0, height - video.height, video);
}
}
}
void keyPressed() {
if (key == 'g') {
saveFrame();
}
else if (key == 'c') {
cheatScreen = !cheatScreen;
}
}
// Functions to handle sorting the color data
void sort(int length, int[] a, Tuple[] stuff) {
sortSub(a, stuff, 0, length - 1);
}
void sortSwap(int[] a, Tuple[] stuff, int i, int j) {
int T = a[i];
a[i] = a[j];
a[j] = T;
Tuple v = stuff[i];
stuff[i] = stuff[j];
stuff[j] = v;
}
void sortSub(int[] a, Tuple[] stuff, int lo0, int hi0) {
int lo = lo0;
int hi = hi0;
int mid;
if (hi0 > lo0) {
mid = a[(lo0 + hi0) / 2];
while (lo <= hi) {
while ((lo < hi0) && (a[lo] < mid)) {
++lo;
}
while ((hi > lo0) && (a[hi] > mid)) {
--hi;
}
if (lo <= hi) {
sortSwap(a, stuff, lo, hi);
++lo;
--hi;
}
}
if (lo0 < hi)
sortSub(a, stuff, lo0, hi);
if (lo < hi0)
sortSub(a, stuff, lo, hi0);
}
}
@@ -0,0 +1,29 @@
// Simple vector class that holds an x,y,z position.
class Tuple {
float x, y, z;
Tuple() { }
Tuple(float x, float y, float z) {
set(x, y, z);
}
void set(float x, float y, float z) {
this.x = x;
this.y = y;
this.z = z;
}
void target(Tuple another, float amount) {
float amount1 = 1.0 - amount;
x = x*amount1 + another.x*amount;
y = y*amount1 + another.y*amount;
z = z*amount1 + another.z*amount;
}
void phil() {
fill(x, y, z);
}
}
@@ -0,0 +1,64 @@
/**
* Frame Differencing
* by Golan Levin.
*
* Quantify the amount of movement in the video frame using frame-differencing.
*/
import processing.video.*;
int numPixels;
int[] previousFrame;
Capture video;
void setup() {
size(640, 480); // Change size to 320 x 240 if too slow at 640 x 480
// Uses the default video input, see the reference if this causes an error
video = new Capture(this, width, height, 24);
numPixels = video.width * video.height;
// Create an array to store the previously captured frame
previousFrame = new int[numPixels];
loadPixels();
}
void draw() {
if (video.available()) {
// When using video to manipulate the screen, use video.available() and
// video.read() inside the draw() method so that it's safe to draw to the screen
video.read(); // Read the new frame from the camera
video.loadPixels(); // Make its pixels[] array available
int movementSum = 0; // Amount of movement in the frame
for (int i = 0; i < numPixels; i++) { // For each pixel in the video frame...
color currColor = video.pixels[i];
color prevColor = previousFrame[i];
// Extract the red, green, and blue components from current pixel
int currR = (currColor >> 16) & 0xFF; // Like red(), but faster
int currG = (currColor >> 8) & 0xFF;
int currB = currColor & 0xFF;
// Extract red, green, and blue components from previous pixel
int prevR = (prevColor >> 16) & 0xFF;
int prevG = (prevColor >> 8) & 0xFF;
int prevB = prevColor & 0xFF;
// Compute the difference of the red, green, and blue values
int diffR = abs(currR - prevR);
int diffG = abs(currG - prevG);
int diffB = abs(currB - prevB);
// Add these differences to the running tally
movementSum += diffR + diffG + diffB;
// Render the difference image to the screen
pixels[i] = color(diffR, diffG, diffB);
// The following line is much faster, but more confusing to read
//pixels[i] = 0xff000000 | (diffR << 16) | (diffG << 8) | diffB;
// Save the current color into the 'previous' buffer
previousFrame[i] = currColor;
}
// To prevent flicker from frames that are all black (no movement),
// only update the screen if the image has changed.
if (movementSum > 0) {
updatePixels();
println(movementSum); // Print the total amount of movement to the console
}
}
}
@@ -0,0 +1,58 @@
/**
* Framingham
* by Ben Fry.
*
* Show subsequent frames from video input as a grid. Also fun with movie files.
*/
import processing.video.*;
Capture video;
int column;
int columnCount;
int lastRow;
// Buffer used to move all the pixels up
int[] scoot;
void setup() {
size(640, 480, P2D);
// Uses the default video input, see the reference if this causes an error
video = new Capture(this, 32, 24);
// Also try with other video sizes
column = 0;
columnCount = width / video.width;
int rowCount = height / video.height;
lastRow = rowCount - 1;
scoot = new int[lastRow*video.height * width];
background(0);
}
void draw() {
// By using video.available, only the frame rate need be set inside setup()
if (video.available()) {
video.read();
set(video.width*column, video.height*lastRow, video);
column++;
if (column == columnCount) {
loadPixels();
// Scoot everybody up one row
arraycopy(pixels, video.height*width, scoot, 0, scoot.length);
arraycopy(scoot, 0, pixels, 0, scoot.length);
// Set the moved row to black
for (int i = scoot.length; i < width*height; i++) {
pixels[i] = #000000;
}
column = 0;
updatePixels();
}
}
}
@@ -0,0 +1,38 @@
/**
* Getting Started with Capture.
*
* Reading and displaying an image from an attached Capture device.
*/
import processing.video.*;
Capture cam;
void setup() {
size(640, 480);
// If no device is specified, will just use the default.
cam = new Capture(this, 320, 240);
// To use another device (i.e. if the default device causes an error),
// list all available capture devices to the console to find your camera.
//String[] devices = Capture.list();
//println(devices);
// Change devices[0] to the proper index for your camera.
//cam = new Capture(this, width, height, devices[0]);
// Opens the settings page for this capture device.
//camera.settings();
}
void draw() {
if (cam.available() == true) {
cam.read();
image(cam, 160, 100);
// The following does the same, and is faster when just drawing the image
// without any additional resizing, transformations, or tint.
//set(160, 100, cam);
}
}
@@ -0,0 +1,206 @@
/**
* HSV Space
* by Ben Fry.
*
* Arrange the pixels from live video into the HSV Color Cone.
*/
import processing.opengl.*;
import processing.video.*;
Capture video;
int count;
boolean cheatScreen = true;
static final float BOX_SIZE = 0.75;
static final float CONE_HEIGHT = 1.2;
static final float MAX_RADIUS = 10;
static final float ROT_INCREMENT = 3.0;
static final float TRANS_INCREMENT = 1;
static final float STEP_AMOUNT = 0.1;
Tuple[] farbe;
Tuple[] trans;
float[] hsb = new float[3];
float leftRightAngle;
float upDownAngle;
float fwdBackTrans;
float upDownTrans;
float leftRightTrans;
boolean motion;
boolean blobby = false;
void setup() {
size(640, 480, P3D);
//size(screen.width, screen.height, OPENGL);
video = new Capture(this, 40, 30, 15);
count = video.width * video.height;
sphereDetail(60);
upDownTrans = 0;
leftRightTrans = 0;
motion = false;
leftRightAngle = 101.501297;
upDownAngle = -180.098694;
fwdBackTrans = 14.800003;
farbe = new Tuple[count];
trans = new Tuple[count];
for (int i = 0; i < count; i++) {
farbe[i] = new Tuple();
trans[i] = new Tuple();
}
}
void draw() {
background(0);
if (!blobby) lights();
pushMatrix();
translate(width/2, height/2);
scale(min(width, height) / 10.0);
translate(0, 0, -20 + fwdBackTrans);
rotateY(radians(36 + leftRightAngle)); //, 0, 1, 0);
rotateX(radians(-228 + upDownAngle)); //, 1, 0, 0);
if (blobby) {
stroke(0.35, 0.35, 0.25, 0.15);
wireCone(MAX_RADIUS, MAX_RADIUS * CONE_HEIGHT, 18, 18);
}
else {
stroke(0.35, 0.35, 0.25, 0.25);
wireCone(MAX_RADIUS, MAX_RADIUS * CONE_HEIGHT, 180, 18);
}
noStroke();
for (int i = 0; i < count; i++) {
int pixelColor = video.pixels[i];
int r = (pixelColor >> 16) & 0xff;
int g = (pixelColor >> 8) & 0xff;
int b = pixelColor & 0xff;
Color.RGBtoHSB(r, g, b, hsb);
float radius = hsb[1] * hsb[2];
float angle = hsb[0] * 360.0 * DEG_TO_RAD;
float nx = MAX_RADIUS * radius * cos(angle);
float ny = MAX_RADIUS * radius * sin(angle);
float nz = hsb[2] * MAX_RADIUS * CONE_HEIGHT;
trans[i].set(trans[i].x - (trans[i].x - nx)*STEP_AMOUNT,
trans[i].y - (trans[i].y - ny)*STEP_AMOUNT,
trans[i].z - (trans[i].z - nz)*STEP_AMOUNT);
farbe[i].set(farbe[i].x - (farbe[i].x - r)*STEP_AMOUNT,
farbe[i].y - (farbe[i].y - g)*STEP_AMOUNT,
farbe[i].z - (farbe[i].z - b)*STEP_AMOUNT);
pushMatrix();
farbe[i].phil();
trans[i].tran();
rotate(radians(45), 1, 1, 0);
if (blobby) {
sphere(BOX_SIZE * 2); //, 20, 20);
} else {
box(BOX_SIZE);
}
popMatrix();
}
popMatrix();
if (motion) {
upDownAngle--;
leftRightAngle--;
}
if (cheatScreen) {
image(video, 0, height - video.height);
}
}
void captureEvent(Capture c) {
c.read();
c.loadPixels();
}
void keyPressed() {
switch (key) {
case 'g':
saveFrame();
break;
case 'c':
cheatScreen = !cheatScreen;
break;
case 'm':
motion = !motion;
break;
case '=':
fwdBackTrans += TRANS_INCREMENT;
break;
case '-':
fwdBackTrans -= TRANS_INCREMENT;
break;
case 'b':
blobby = !blobby;
break;
}
}
void mouseDragged() {
float dX, dY;
switch (mouseButton) {
case LEFT: // left right up down
dX = pmouseX - mouseX;
dY = pmouseY - mouseY;
leftRightAngle -= dX * 0.2;
upDownAngle += dY * 0.4;
break;
case CENTER:
dX = pmouseX - mouseX;
dY = pmouseY - mouseY;
leftRightTrans -= TRANS_INCREMENT * dX;
upDownTrans -= TRANS_INCREMENT * dY;
break;
case RIGHT: // in and out
dY = (float) (pmouseY - mouseY);
fwdBackTrans -= TRANS_INCREMENT * dY;
break;
}
}
void wireCone(float radius, float height, int stepX, int stepY) {
int steps = 10;
stroke(40);
for (int i = 0; i < steps; i++) {
float angle = map(i, 0, steps, 0, TWO_PI);
float x = radius * cos(angle);
float y = radius * sin(angle);
line(x, y, height, 0, 0, 0);
}
noFill();
pushMatrix();
translate(0, 0, height);
ellipseMode(CENTER_RADIUS);
ellipse(0, 0, radius, radius);
popMatrix();
}
@@ -0,0 +1,33 @@
// Simple vector class that holds an x,y,z position.
class Tuple {
float x, y, z;
Tuple() { }
Tuple(float x, float y, float z) {
set(x, y, z);
}
void set(float x, float y, float z) {
this.x = x;
this.y = y;
this.z = z;
}
void target(Tuple another, float amount) {
float amount1 = 1.0 - amount;
x = x*amount1 + another.x*amount;
y = y*amount1 + another.y*amount;
z = z*amount1 + another.z*amount;
}
void phil() {
fill(x, y, z);
}
void tran() {
translate(x, y, z);
}
}
@@ -0,0 +1,53 @@
/**
* Live Pocky
* by Ben Fry.
*
* Unwrap each frame of live video into a single line of pixels.
*/
import processing.video.*;
Capture video;
int count;
int writeRow;
int maxRows;
int topRow;
int buffer[];
void setup() {
size(600, 400);
// Uses the default video input, see the reference if this causes an error
video = new Capture(this, 30, 20);
maxRows = height * 2;
buffer = new int[width * maxRows];
writeRow = height - 1;
topRow = 0;
//frameRate(10);
background(0);
loadPixels();
}
void draw() {
for (int y = 0; y < height; y++) {
int row = (topRow + y) % maxRows;
arraycopy(buffer, row * width, g.pixels, y*width, width);
}
updatePixels();
}
void captureEvent(Capture c) {
c.read();
c.loadPixels();
arraycopy(c.pixels, 0, buffer, writeRow * width, width);
writeRow++;
if (writeRow == maxRows) {
writeRow = 0;
}
topRow++;
}
@@ -0,0 +1,72 @@
/**
* Mirror
* by Daniel Shiffman.
*
* Each pixel from the video source is drawn as a rectangle with rotation based on brightness.
*/
import processing.video.*;
// Size of each cell in the grid
int cellSize = 20;
// Number of columns and rows in our system
int cols, rows;
// Variable for capture device
Capture video;
void setup() {
size(640, 480, P2D);
frameRate(30);
cols = width / cellSize;
rows = height / cellSize;
colorMode(RGB, 255, 255, 255, 100);
// Uses the default video input, see the reference if this causes an error
video = new Capture(this, width, height, 12);
background(0);
}
void draw() {
if (video.available()) {
video.read();
video.loadPixels();
// Not bothering to clear background
// background(0);
// Begin loop for columns
for (int i = 0; i < cols; i++) {
// Begin loop for rows
for (int j = 0; j < rows; j++) {
// Where are we, pixel-wise?
int x = i*cellSize;
int y = j*cellSize;
int loc = (video.width - x - 1) + y*video.width; // Reversing x to mirror the image
float r = red(video.pixels[loc]);
float g = green(video.pixels[loc]);
float b = blue(video.pixels[loc]);
// Make a new color with an alpha component
color c = color(r, g, b, 75);
// Code for drawing a single rect
// Using translate in order for rotation to work properly
pushMatrix();
translate(x+cellSize/2, y+cellSize/2);
// Rotation formula based on brightness
rotate((2 * PI * brightness(c) / 255.0));
rectMode(CENTER);
fill(c);
noStroke();
// Rects are larger than the cell for some overlap
rect(0, 0, cellSize+6, cellSize+6);
popMatrix();
}
}
}
}
@@ -0,0 +1,59 @@
/**
* Mirror 2
* by Daniel Shiffman.
*
* Each pixel from the video source is drawn as a rectangle with size based on brightness.
*/
import processing.video.*;
// Size of each cell in the grid
int cellSize = 15;
// Number of columns and rows in our system
int cols, rows;
// Variable for capture device
Capture video;
void setup() {
size(630, 480, P2D);
//set up columns and rows
cols = width / cellSize;
rows = height / cellSize;
colorMode(RGB, 255, 255, 255, 100);
rectMode(CENTER);
// Uses the default video input, see the reference if this causes an error
video = new Capture(this, width, height, 15);
background(0);
}
void draw() {
if (video.available()) {
video.read();
video.loadPixels();
background(0, 0, 255);
// Begin loop for columns
for (int i = 0; i < cols;i++) {
// Begin loop for rows
for (int j = 0; j < rows;j++) {
// Where are we, pixel-wise?
int x = i * cellSize;
int y = j * cellSize;
int loc = (video.width - x - 1) + y*video.width; // Reversing x to mirror the image
// Each rect is colored white with a size determined by brightness
color c = video.pixels[loc];
float sz = (brightness(c) / 255.0) * cellSize;
fill(255);
noStroke();
rect(x + cellSize/2, y + cellSize/2, sz, sz);
}
}
}
}
@@ -0,0 +1,74 @@
/**
* Radial Pocky
* by Ben Fry.
*
* Unwrap each frame of live video into a single line of pixels along a circle
*/
import processing.video.*;
Capture video;
int videoCount;
int currentAngle;
int pixelCount;
int angleCount = 200; // how many divisions
int radii[];
int angles[];
void setup() {
// size must be set to video.width*video.height*2 in both directions
size(960, 540);
// Uses the default video input, see the reference if this causes an error
video = new Capture(this, 24, 16);
videoCount = video.width * video.height;
pixelCount = width*height;
int centerX = width / 2;
int centerY = height / 2;
radii = new int[pixelCount];
angles = new int[pixelCount];
int offset = 0;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int dx = centerX - x;
int dy = centerY - y;
float angle = atan2(dy, dx);
if (angle < 0) angle += TWO_PI;
angles[offset] = (int) (angleCount * (angle / TWO_PI));
int radius = (int) mag(dx, dy);
if (radius >= videoCount) {
radius = -1;
angles[offset] = -1;
}
radii[offset] = radius;
offset++;
}
}
background(0);
}
void draw() {
if (video.available()) {
video.read();
video.loadPixels();
loadPixels();
for (int i = 0; i < pixelCount; i++) {
if (angles[i] == currentAngle) {
pixels[i] = video.pixels[radii[i]];
}
}
updatePixels();
currentAngle++;
if (currentAngle == angleCount) currentAngle = 0;
}
}
@@ -0,0 +1,54 @@
/**
* Simple Real-Time Slit-Scan Program.
* By Golan Levin.
*
* This demonstration depends on the canvas height being equal
* to the video capture height. If you would prefer otherwise,
* consider using the image copy() function rather than the
* direct pixel-accessing approach I have used here.
*
* Created December 2006.
* Updated June 2007 by fry.
*/
import processing.video.*;
Capture video;
int videoSliceX;
int drawPositionX;
void setup() {
size(600, 240, P2D);
// Uses the default video input, see the reference if this causes an error
video = new Capture(this, 320, 240, 30);
videoSliceX = video.width / 2;
drawPositionX = width - 1;
background(0);
}
void draw() {
if (video.available()) {
video.read();
video.loadPixels();
// Copy a column of pixels from the middle of the video
// To a location moving slowly across the canvas.
loadPixels();
for (int y = 0; y < video.height; y++){
int setPixelIndex = y*width + drawPositionX;
int getPixelIndex = y*video.width + videoSliceX;
pixels[setPixelIndex] = video.pixels[getPixelIndex];
}
updatePixels();
drawPositionX--;
// Wrap the position back to the beginning if necessary.
if (drawPositionX < 0) {
drawPositionX = width - 1;
}
}
}