«first  …11 12 13 14 15 16 17 last»

redUniverse: Support for Discrete Worlds

2010-12-15 06:22 supercollider

clean-up #30:

As the last thing for this month-of-cleaning-up-old-code-and-taking-care-of-forgotten-projects, I finally wrote some methods that I had been planning for a long time. They add support for discrete worlds to my redUniverse quark.

It's all fairly simple.

In a 2 dimensional world there are 8 neighbouring cells/locations. The surroundings method returns them.

a= RedWorld(RedVector[100, 200])  //a 2D world
a.surroundings
[ [ -1, -1 ], [ -1, 0 ], [ -1, 1 ], [ 0, -1 ], [ 0, 1 ], [ 1, -1 ], [ 1, 0 ], [ 1, 1 ] ]

And in a 3 dimensional world, the number of surrounding cells grows to 26. That is 3 * 3 * 3 - 1 where the minus one is the [0, 0] location.

a= RedWorld(RedVector[100, 200, 300])  //a 3D world
a.surroundings
[ [ -1, -1, -1 ], [ -1, -1, 0 ], [ -1, -1, 1 ], [ -1, 0, -1 ], [ -1, 0, 0 ], [ -1, 0, 1 ], [ -1, 1, -1 ], [ -1, 1, 0 ], [ -1, 1, 1 ], [ 0, -1, -1 ], [ 0, -1, 0 ], [ 0, -1, 1 ], [ 0, 0, -1 ], [ 0, 0, 1 ], [ 0, 1, -1 ], [ 0, 1, 0 ], [ 0, 1, 1 ], [ 1, -1, -1 ], [ 1, -1, 0 ], [ 1, -1, 1 ], [ 1, 0, -1 ], [ 1, 0, 0 ], [ 1, 0, 1 ], [ 1, 1, -1 ], [ 1, 1, 0 ], [ 1, 1, 1 ] ]

And the numbers for 4, 5 and 6 dimensional worlds (not that I ever used >3) are 80, 242, 728 respectively. (A RedWorld can have any number of dimensions.)

Also it is possible to not only get the directly adjacent cell, but neighbours further away. This example bumps up the surroundingArea variable from the default 1 to 2. Now the surroundings are all the cells next to and two steps away from [0, 0].

a= RedWorld(RedVector[100, 200])  //a 2F world
a.surroundingArea= 2
a.surroundings
[ [ -2, -2 ], [ -2, -1 ], [ -2, 0 ], [ -2, 1 ], [ -2, 2 ], [ -1, -2 ], [ -1, -1 ], [ -1, 0 ], [ -1, 1 ], [ -1, 2 ], [ 0, -2 ], [ 0, -1 ], [ 0, 1 ], [ 0, 2 ], [ 1, -2 ], [ 1, -1 ], [ 1, 0 ], [ 1, 1 ], [ 1, 2 ], [ 2, -2 ], [ 2, -1 ], [ 2, 0 ], [ 2, 1 ], [ 2, 2 ] ]

That is 24 neighbour locations per single cell in a 2D world.

So the surroundings method only give relative positions and the size of the neighbourhood. Not so useful. But there are the two other methods called surroundingLocations and neighbours that is what one should use. surroundingLocations takes an object and returns a list of locations depending on the current surroundings.

a= RedWorld(RedVector[100, 200])  //a 2D world
b= RedObject(a, RedVector[10, 20])  //an object at location [10, 20]
a.surroundingLocations(b)  //get the surrounding locations of object b
[ RedVector[ 9, 19 ], RedVector[ 9, 20 ], RedVector[ 9, 21 ], RedVector[ 10, 19 ], RedVector[ 10, 21 ], RedVector[ 11, 19 ], RedVector[ 11, 20 ], RedVector[ 11, 21 ] ]

Last the neighbours method that returns an array of any nearby objects.

a= RedWorld(RedVector[100, 200])  //a 2D world
b= RedObject(a, RedVector[10, 20])  //an object at location [10, 20]
c= RedObject(a, RedVector[11, 21])  //an object at location [11, 21]
a.neighbours(b)  //get the neighbouring objects of object b
[ a RedObject ]

The different worlds deals with border conditions differently. RedWorld wraps all the locations around and RedWorld3 filters out locations. Compare...

a= RedWorld(RedVector[100, 200])  //a 2D world without borders
b= RedObject(a, RedVector[0, 0])  //an object at upper left corner location [0, 0]
a.surroundingLocations(b)  //get the surrounding locations of object b
[ RedVector[ 99, 199 ], RedVector[ 99, 0 ], RedVector[ 99, 1 ], RedVector[ 0, 199 ], RedVector[ 0, 1 ], RedVector[ 1, 199 ], RedVector[ 1, 0 ], RedVector[ 1, 1 ] ]
a= RedWorld3(RedVector[100, 200])  //a 2D world with borders
b= RedObject(a, RedVector[0, 0])  //an object at upper left corner location [0, 0]
a.surroundingLocations(b)  //get the surrounding locations of object b
[ RedVector[ 0, 1 ], RedVector[ 1, 0 ], RedVector[ 1, 1 ] ]

The neighbours method is quite slow at the moment, but I hope to be able to speed it up considerably later on.

Anyway, here is the complete SVN diff: sourceforge.net/p/quarks/code/1765/



redLeech

2010-12-13 03:21 supercollider

clean-up #28:

Code that performs itself. This is number six in a series all working in a similar manner. See low life, more low life and even more low life.

This virtual leech runs around the code and sucks up words now and then. When it's full (c.size>30) it spits them all out wherever it happens to be. And some characters are lost so the code slowly disappears.

At the end of the video, it got stuck in a loop so I killed it off manually with the delete key.

Thanks to Chris for the title.

SuperCollider document attached below. Will only run under older SuperCollider with OSX (Cocoa, <3.6) AFAIK.

Attachments:
redLeech.scd


redUniverse: Clean-up and some New Features

2010-12-11 04:01 supercollider

clean-up #26:

My redUniverse quark still has a lot of features missing that I want to put in. It is endless work and I only get to it now and then. But at least after today the help files are in a bit better shape, and examples are changed to use animate to run more smoothly (most now look a lot better!).

  • new help files for RedHiddenObject, RedParticle, RedBoid, RedRock, RedFood, RedAgent.
  • slightly changed formatting for almost all the other included help files.
  • wrote addForceWander1D and addForceWander3D methods for RedBoid.
  • wrote addForceAngular3D, pendulumOffset3D, pendulumLoc3D.
  • added 2 boids examples and 1 pendulum to show the new features.
  • changed almost all the other examples to use animate instead of play and to close the window at cmd+.

Here is the complete SVN diff: sourceforge.net/p/quarks/code/1759/


Vertex

2010-12-10 05:01 supercollider

clean-up #25:

Attached is a little class that draws polygons in SuperCollider. With inspiration from processing.org/reference/beginShape_.html.

If you want to use the \points type of shape it will look better with smoothing set to false and Vertex.pointSize= 0;

vertextest screenshot

(
var win= Window("vertex test", Rect(100, 100, 430, 320), false);
win.drawFunc= {
    Pen.fillColor= Color.white;
    Pen.strokeColor= Color.black;
    
    Pen.use{
        Pen.translate(10, 10);
        Vertex.beginShape();
        Vertex(Point(30, 20));
        Vertex(Point(85, 20));
        Vertex(Point(85, 75));
        Vertex(Point(30, 75));
        Vertex.endShape(1);  //1 means close
        Pen.fillStroke;  //also try fill and stroke
    };
    Pen.use{
        Pen.translate(110, 10);
        Vertex.beginShape(\points);
        Vertex(Point(30, 20));
        Vertex(Point(85, 20));
        Vertex(Point(85, 75));
        Vertex(Point(30, 75));
        Vertex.endShape();
        Pen.stroke;
    };
    Pen.use{
        Pen.translate(210, 10);
        Vertex.beginShape(\lines);
        Vertex(Point(30, 20));
        Vertex(Point(85, 20));
        Vertex(Point(85, 75));
        Vertex(Point(30, 75));
        Vertex.endShape();
        Pen.stroke;
    };
    Pen.use{
        Pen.translate(310, 10);
        Vertex.beginShape();
        Vertex(Point(30, 20));
        Vertex(Point(85, 20));
        Vertex(Point(85, 75));
        Vertex(Point(30, 75));
        Vertex.endShape(0);  //0 means not close (default)
        Pen.stroke;
    };
    
    Pen.use{
        Pen.translate(10, 110);
        Vertex.beginShape();
        Vertex(Point(30, 20));
        Vertex(Point(85, 20));
        Vertex(Point(85, 75));
        Vertex(Point(30, 75));
        Vertex.endShape(1);  //1 means close
        Pen.stroke;
    };
    Pen.use{
        Pen.translate(110, 110);
        Vertex.beginShape(\triangles);
        Vertex(Point(30, 75));
        Vertex(Point(40, 20));
        Vertex(Point(50, 75));
        Vertex(Point(60, 20));
        Vertex(Point(70, 75));
        Vertex(Point(80, 20));
        Vertex.endShape();
        Pen.fillStroke;  //also try fill and stroke
    };
    Pen.use{
        Pen.translate(210, 110);
        Vertex.beginShape(\triangleStrip);
        Vertex(Point(30, 75));
        Vertex(Point(40, 20));
        Vertex(Point(50, 75));
        Vertex(Point(60, 20));
        Vertex(Point(70, 75));
        Vertex(Point(80, 20));
        Vertex(Point(90, 75));
        Vertex.endShape();
        Pen.fillStroke;  //also try fill and stroke
    };
    Pen.use{
        Pen.translate(310, 110);
        Vertex.beginShape(\triangleFan);
        Vertex(Point(57.5, 50));
        Vertex(Point(57.5, 15));
        Vertex(Point(92, 50));
        Vertex(Point(57.5, 85));
        Vertex(Point(22, 50));
        Vertex(Point(57.5, 15));
        Vertex.endShape();
        Pen.fillStroke;  //also try fill and stroke
    };
    
    Pen.use{
        Pen.translate(10, 210);
        Vertex.beginShape(\quads);
        Vertex(Point(30, 20));
        Vertex(Point(30, 75));
        Vertex(Point(50, 75));
        Vertex(Point(50, 20));
        Vertex(Point(65, 20));
        Vertex(Point(65, 75));
        Vertex(Point(85, 75));
        Vertex(Point(85, 20));
        Vertex.endShape();
        Pen.fillStroke;  //also try fill and stroke
    };
    Pen.use{
        Pen.translate(110, 210);
        Vertex.beginShape(\quadStrip);
        Vertex(Point(30, 20));
        Vertex(Point(30, 75));
        Vertex(Point(50, 20));
        Vertex(Point(50, 75));
        Vertex(Point(65, 20));
        Vertex(Point(65, 75));
        Vertex(Point(85, 20));
        Vertex(Point(85, 75));
        Vertex.endShape();
        Pen.fillStroke;  //also try fill and stroke
    };
    Pen.use{
        Pen.translate(210, 210);
        Vertex.beginShape();
        Vertex(Point(20, 20));
        Vertex(Point(40, 20));
        Vertex(Point(40, 40));
        Vertex(Point(60, 40));
        Vertex(Point(60, 60));
        Vertex(Point(20, 60));
        Vertex.endShape(1);  //also try 0 here
        Pen.fillStroke;  //also try fill and stroke
    };
    Pen.use{
        Pen.translate(310, 210);
        Vertex.beginShape();
        14.do{
            Vertex(Point(85.rand, 85.rand));
        };
        Vertex.endShape(1);  //also try 0 here
        Pen.fillStroke;  //also try fill and stroke
    };
};
win.front;
)
//https://processing.org/reference/bezierVertex_.html
(
var win= Window("beziervertex test1", Rect(100, 100, 300, 300), false);
win.drawFunc= {
    Pen.fillColor= Color.white;
    Pen.strokeColor= Color.black;
    BezierVertex.beginShape(Point(30, 20));
    BezierVertex(Point(80, 0), Point(80, 75), Point(30, 75));
    BezierVertex.endShape;
    Pen.stroke;  //also try fillStroke and fill
};
win.front;
)

//https://processing.org/reference/bezierVertex_.html
(
var win= Window("beziervertex test2", Rect(100, 100, 300, 300), false);
win.drawFunc= {
    Pen.fillColor= Color.white;
    Pen.strokeColor= Color.black;
    BezierVertex.beginShape(Point(30, 20));
    BezierVertex(Point(80, 0), Point(80, 75), Point(30, 75));
    BezierVertex(Point(50, 80), Point(60, 25), Point(30, 20));
    BezierVertex.endShape;
    Pen.fillStroke;  //also try stroke and fill
};
win.front;
)

Updates:

  • 101211: attached a simple BezierVertez class. It works like processing.org/reference/bezierVertex_.html.
  • 101215: improved the \triangleFan type in Vertex.sc.
  • 141012: minor update to BezierVertez.sc - added close argument
  • 180101: examples updated for sc3.9 (drawFunc instead of drawHook)
Attachments:
Vertex.sc
BezierVertex.sc

K-means

2010-12-09 03:14 supercollider

clean-up #24:

I took some code I had for performing K-means clustering and made it into a proper class. I also found Dan Stowell's KMeans quark and borrowed some concepts from that one. My version works slightly different and uses RedVectors of any dimension.

The class is part of my redUniverse quark and the best way to install it is as always to from within SuperCollider type... Quarks.install("redUniverse"); and then recompile. A help file and simple examples are included but I hope to write more elaborate demonstrations of this later on.

This is a screenshot from the example in the RedKMeans help file. 1000 random points are categorised into 5 groups/clusters. The bigger circles are the 5 mean points/centroids.

kmeans screenshot

Also, see 190-kmeans.scd for an example running in realtime.


anneVideotracking

2010-12-08 04:08 supercollider, visuals

clean-up #23:

The screenshot below is of a simple little mac application I made in MaxMSPJitter. It takes realtime input from a web or DV-camera, chops it into six regions and tracks activity in each of those regions separately. The result is sent over to SuperCollider via OSC.

The analysis/tracking is just a simple average luminescence per frame. That is, it takes the mean of all the red, green and blue values in one frame and then calculate the luma with (0.299*red)+(0.587*green)+(0.114*blue). The luma will be close to 0 for dark frames and close to 1 for very bright video frames.

To tune this system to produce maximal output, one should first make sure the camera sits still and has sufficient and stable light. Then in the software there are colour, brightness and contrast controls to help get even better readings. (Completely inverting all the colours might help in really dark places.)

The luma values (float 0.0-1.0) can be rounded off to nearest number and also smoothed out. This is often necessary to avoid flutter and noise. And most important - there is manual calibration of the luma values - either per region or globally.

To calibrate one should first empty the camera's view of any objects and then press the 'calibrate min' button in the lower-left corner. Then move some objects around to see what is the maximum reading. Last put that number into the 'set max' number box. One can also calibrate each region separately with the min and max buttons next to the preview windows.

Download the mac OSX standalone from /code/apps/#annevideotracking.

anneVideotracking screenshot

and here is SuperCollider code to read the data and make some simple sounds out of it.

//to start: select all + enter
//to stop: cmd + .
(
n= 6;
s.latency= 0.05;
s.waitForBoot{
    var dlast= 0.dup(n);
    d= {Bus.control(s, 1)}.dup(n);
    e= {Bus.control(s, 1)}.dup(n);
    OSCFunc({|m|
        var index= m[1], val= m[2], diff= (val-dlast[index]).abs;
        //m.postln;
        d[index].set(val);
        e[index].set(diff);
        dlast.put(index, val);
    }, \anneVideoTracking);
    CmdPeriod.doOnce({d.do{|x| x.free}; e.do{|x| x.free}});
    SynthDef(\annetest, {
        var src= Mix({|i| SinOsc.ar(i*100+400, 0, LagUD.kr(In.kr(e[i].index), 0.01, 0.1))}.dup(n));
        Out.ar(0, Pan2.ar(src));
    }).add;
    s.sync;
    Synth(\annetest);
};
)

Updates:


«first  …11 12 13 14 15 16 17 last»