The Cabinet installation, Worchestershire, a set on Flickr.
The goal of this project was to create an interactive installation that got kids (and others) dancing and moving about. Using augmented reality, we created an installation that people needed to “dance” around in order to achieve the goal – setting the imprisoned Creaturae Aquae free from inside the cabinet of a Collector of Magical Creatures.
We consulted with a choreographer, and used Cinder, Animata, and ARToolKitPlus three open source technologies, to make an game for public spaces that up to 16 people could play with simultaneously. The end result was fun, and people from young to old got the idea very quickly and started dancing about! The lovely instruction card, with the AR marker (a pair of scissors) on it, was a big help.
[youtube 640 480 http://youtu.be/rWivizbwJuA]
Via Flickr:
12moves.com/blog/events/26
The Creaturae Aquae is trapped in a cabinet by a collector of weird and wonderful things, pinned down and held captive by ropes. Set the creaturae free! Use one (or more) of the cards with the scissors symbol next to the creaturae, hold it up in front of the cabinet, and magical scissors will appear. Dance with the scissors to cut the ropes and let the creaturae dance freely!
By SDNA, with animation and programming by pixelpusher
No Comments
oops
Originally uploaded by da mad pixelist
This is why you should never trust the Internets. This is also how I blew out my only phototransistor and IR LED (from RadioShack! 2002! If it wasn’t blown out from sitting in the sun for 8 years, already)
No CommentsI’ve finally had a moment to release this (much better) version of ARToolkitPlus for Cinder, for both Windows and OS X.
Get it here: http://code.google.com/p/artoolkitplus-for-cinder/
![]()
The long of it (otherwise known as the “README” file that comes with it):
INTRODUCTION
This is the libcinder port of ARToolkitPlus by Evan Raskob (sometimes known as pixelpusher) :: http://pixelist.info / info@pixelist.info
The code has a variety of licenses, please refer to the files themselves for their license. The original code from ARToolkitplus - http://studierstube.icg.tu-graz.ac.at/handheld_ar/artoolkitplus.php and ARToolkit – http://www.hitl.washington.edu/artoolkit/ – was released under a GPLv2 license, the new additions (few as they are) are released under the GNU Affero 3.0+ license (which is better) and/or an Apache license (where we don’t care about derivative versions). Sorry for the confusion.
If you find this useful, please let us know! If you find bugs or have other good ideas on how to optimize this code (and there are plenty of ways) then perhaps you’d like to contribute.
WHAT YOU GET
This version includes some example code for tracking multiple AR markers (the venerable Hiro and Kanji) and figuring out their position on the (camera) screen and their 4 boundary points (vertices). It also includes two pre-built libraries for both Windows 7 and OS X 10.6. It will probably work on 10.5 as well, and maybe even Win XP, who knows? There is an XCode project and a Visual Studio 2010 project included, as well as some files gleaned from the ARToolkit and ARToolkitPlus original projects that may come in handy.
INSTALLING AND USING
Well, there’s no real “installation” process – simply copy to your “blocks” folder in your Cinder directory, and the example projects should build and run.
There are, unfortunately, a few caveats.
For one, on Windows I decided to load all the configuration files from a “resources” folder that sites next to the executable file. This is for flexibility, so you could swap different markers and marker config files without re-building the whole project. Another way to do it is to package everything into the EXE itself and use loadResource() to load the data and parse it – that would require changing the guts of ARToolkitplus and isn’t impossible at all but just a slight pain. On OS X, everything is copied into the application itself.
One side-effect of this is that if any configuration files or pattern files are missing, your application will simply crash. D’oh! Of course, you may want to have it fail in a more elegant fashion, but for what I was doing with this project, if it failed than it might as well crash hard because it was useless.
Your results may vary.
If you decide to poke around, the ARToolkitPlus/src/core/ has most of the code you might find useful, especially the files I changed – arGetCode.cxx and arMultiReadConfigFile.cxx. With the old ARToolkitPlus, you could only use numberical pattern ids in the marks config file, with this version you can use file names and your own custom (original ARToolkit-style) template ids, such as in the example.
A BIG PROBLEM is that on Windows you very easily get to the maximum path length, and your app just dies. If it crashs unexpectedly on load, it could be that your code is nestled too deep in a cosy burrow of sub-folders, try building and then copying it to a folder closer to your C: root, or even better, uncomment out my DEBUG 1 compiler define in arGetCode.cxx and your main app and use a hard-coded path while debugging.
WHAT YOU DON’T GET (YET)
It doesn’t do 3D transforms, yet. It could, but they are processing-intensive, and I didn’t need them for this project. In fact, you may not need them either – please have a look at the two included classes to see what I’m talking about.
This version doesn’t do those numbered template markers like this version did: http://pixelist.info/artoolkitplus-in-cinder/ A future version should, or you can help out! It’s not difficult to add that functionality on, just takes time.
In fact, you’d want to do something like make a new class based on the included ARTKpMultiTracker class except with this code (you can see where it should go…)
// create a tracker that does: // - 6x6 sized marker images // - samples at a maximum of 6x6 // - works with luminance (gray) images // - can load a maximum of 1 pattern // - can detect a maximum of 8 patterns in one image ARToolKitPlus::TrackerSingleMarker *tracker = new ARToolKitPlus::TrackerSingleMarkerImpl<6,6,6, 1, 8>(width,height);
Happy coding!
Evan
http://pixelist.info
http://openlabworkshops.org
No CommentsI’ve been thinking recently about Processing and animation. One of the really nice things about it is that it lets you build up visuals from the ground up, from fairly minimal amounts of code and basic shapes. Contrast this with Flash (ActionScript 3.0) where immediately you are using complex objects with a display hierarchy built-in.
Of course, it’s nice to eventually got to some sort of display hierarchy, where you have a system in place for rendering out visual “objects.” At some point, you don’t want to draw rectangles anymore, you really want to start mucking about with complex combinations of shapes and movement. You could graduate towards a real, industrial-strength rendering engine, something like the open source games engine AndEngine (for Android), or something even more powerful and confusion, but there’s not a lot of middle ground. (If there is, please share!)
What I’ve tried to do here is start up a compromise between an engine like AndEngine and, well, the pure basics of drawing things to the screen pixel-by-pixel. I’m calling it Processing-Scenegraph,” and before you jump all over me and tell me it’s not a real scenegraph, well, I know… a proper scenegraph would have transformation nodes and color nodes and probably a compiler that stored local/global transformations in each node and updated when nodes were added/removed. Etc etc etc. But this version is designed for teaching, to be straightforward but also useful to those students starting out with games design and programming, and artists looking to make more complex animations using programming.
Hopefully you’ll find it useful, and please send feedback and post comments, it’s an open source project, after all!
http://code.google.com/p/processing-scenegraph/
No CommentsHappy Holidays! It’s been ages since I posted anything, mostly because I’ve been so busy teaching at UCA Farnham and Openlab Workshops.
Here’s a little something for the holidays. The code is below, and the source image was courtesy of Jan Tik on Flickr.
/**
* Use some pretty particles to trace an image
* Thanks to Flight404 and Cinder for much inspiration:
* http://libcinder.org/docs/v0.8.2/hello_cinder.html
* Also, I used Jan Tik's CC-licensed image from flickr:
* http://www.flickr.com/photos/jantik/308709862/
*
* Copyright (C) 2010 Evan Raskob <evan@flkr.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import processing.opengl.*;
import javax.media.opengl.*;
// uses toxi's toxiclibs for vector functions.. because it's easier -
// http://hg.postspectacular.com/toxiclibs/wiki/Home
import toxi.geom.Vec2D;
final String imgName = "Winter Meal - jantik.jpg"; // make sure this is in your data folder!
PImage bgImage;
ArrayList<Particle> particles = new ArrayList<Particle>();
float D; // base diameter of all particles
float mass = 0.2; // universal mass of all particles
float DIST = 80*80; // min distance for forces to act on
float MIN_DIST = 10; // min dist between mouse positions for adding new particles
boolean drawLines = false; // draw lines btw particles?
boolean saveFrames = false; // save frames sequentially to disk?
int frameIndex = 0; // index of saved frame - better than the built-in version
void setup()
{
// size should be the size of your image. you could make it dynamic if you want...
size(640,480,OPENGL);
hint(ENABLE_OPENGL_4X_SMOOTH) ;
strokeWeight(2.0);
D = min(width,height) / 30; // base diameter of particles on screen size. change this for bigger/smaller particles
bgImage = loadImage(); // background image
DIST = D*D*1.5*1.5; // distance between particles. Smaller = more detail in final image
MIN_DIST = D/4; // see above
}
void draw()
{
PGraphicsOpenGL pgl;
GL gl;
// *** blending setup *** //
pgl = (PGraphicsOpenGL) g;
gl = pgl.beginGL();
gl.glDisable(GL.GL_DEPTH_TEST);
gl.glEnable(GL.GL_BLEND);
// gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE );
gl.glBlendFunc( GL.GL_SRC_ALPHA , GL.GL_ONE_MINUS_DST_COLOR );
pgl.endGL();
// *** end blending setup *** //
// load pixels, for getting source colors
bgImage.loadPixels();
smooth();
background(0);
image(bgImage,0,0); // draw image first.
// add a new particle if the mouse is pressed
if (mousePressed && abs(pmouseX-mouseX) > MIN_DIST)
{
Particle p = new Particle((float)mouseX, (float)mouseY, D);
// p.v.x = 0.01*(pmouseX-mouseX);
// p.v.y = 0.01*(pmouseY-mouseY);
// set max velocity based on screen size
p.MAXV.x = width/200.0;
p.MAXV.y = height/200.0;
particles.add(p);
}
// optional - keep track of "dead" particles, to remove later
ArrayList<Particle> deadParticles = new ArrayList<Particle>();
noStroke();
// go through the particles and update their position data
for (Particle p : particles)
{
p.update();
if (p.alive)
{
color c = bgImage.pixels[((int)p.pos.y)*bgImage.width + (int)p.pos.x];
p.draw(c);
}
else
deadParticles.add(p);
}
// not using this yet... but could...
for (Particle p : deadParticles)
{
particles.remove(p);
p = null;
}
// handle inter-particle forces
repulseParticles();
// save frames in a sequence
if (saveFrames)
{
saveFrame("frame-" + nf(frameIndex,6)+".png");
++frameIndex;
}
}
void keyReleased()
{
if (key == ' ')
{
saveFrame("winter" + random(0,999999) + ".png");
}
else if (key == 'l' || key == 'L') drawLines = !drawLines;
else if (key == 'f') saveFrames = !saveFrames;
}
void repulseParticles()
{
for(int i=0; i<particles.size(); ++i)
{
Particle p0 = particles.get(i);
for(int ii=i+1; ii<particles.size(); ++ii ) {
Particle p1 = particles.get(ii);
Vec2D dir = p0.pos.sub(p1.pos);
float distSquared = dir.magSquared();
if( distSquared > 0.0f && distSquared <= DIST)
{
dir.normalize();
float F = min(0.2, 1.0f/distSquared) / mass;
dir.scaleSelf( F );
if (drawLines)
{
//stroke(255,80);
stroke(0,200,0);
stroke(p0.c);
line(p0.pos.x, p0.pos.y, p1.pos.x, p1.pos.y);
}
p0.a.addSelf(dir);
p1.a.subSelf(dir);
}
}
}
}
// a simple Particle class with acceleration and velocity
class Particle
{
Vec2D MAXV = new Vec2D(2,2); // max velocity this particle can have (absolute)
Vec2D pos; // position
Vec2D v; // instantaneous velocity
Vec2D a; // instantaneous acceleration
float d; // diameter
color c; // color
boolean alive = false;
Particle(float _x, float _y, float _d)
{
pos = new Vec2D(_x,_y);
v = new Vec2D();
a = new Vec2D();
d = _d;
alive = true;
}
void draw(color _c)
{
c = _c;
fill(c);
float bd = d*(0.9*brightness(c)/255.0 + 0.1);
ellipse(pos.x, pos.y, bd,bd);
}
void update()
{
if (v.x > MAXV.x)
v.x = MAXV.x;
if (v.x < -MAXV.x)
v.x = -MAXV.x;
if (v.y > MAXV.y)
v.y = MAXV.y;
if (v.y < -MAXV.y)
v.y = -MAXV.y;
pos.addSelf(v);
v.scaleSelf(0.95);
v.x += a.x;
v.y += a.y;
a.scaleSelf(0.5);
// if (pos.x >= width || pos.x <= 0 ||
// pos.y >= height || pos.y <= 0)
if (pos.x >= width || pos.x <= 0)
{
//alive = false;
pos.x = constrain(pos.x, 0, width-1);
v.x = -v.x;
a.x = 0;
}
if (pos.y >= height || pos.y <= 0)
{
//alive = false;
pos.y = constrain(pos.y, 0, height-1);
v.y = -v.y;
a.y = 0;
}
}
}
No Comments
Originally uploaded by da mad pixelist
For an upcoming exhibition (my first solo exhibition) I’ve been working on a series of 5-7 new works, from interactive software to prints to sculpture. These tests are from a live capture of my hand opening and closing in front of a camera attached to the computer, using custom written software (a bit of OpenFrameworks and lots of standard C++) that exports each individual motion into a vector-graphics file (SVG) that I can edit and send to a laser-cutter (in our excellent arts workshops at UCA Farnham) to create a sculpture that solidifies the motion into a physical object.
This test is about 80% size, and about 25% of the total slices (the rest I will add this week). Its using 6mm plywood from the local building shop, and will be 78 unique slices in total when finished, connected together at the bottom via a metal cable.
Exhibition details:
24 May – 29 May – Waving / Drowning
An interactive exhibition by pixelpusher – pixelist.info/
This series of works re-imagines the artist’s hand in a number of different mediums as a series of modern mystical symbols. Their meaning is uncertain, removed from their traditional context: are they waving at us, or flailing in a sea of lost meaning?
No CommentsA visualization of each individual word used in twitter status updates overnight from 6PM GMT on Feb 22 2010 until 10AM GMT on Feb 23. Movement is caused by the list of words growing, as the program sees more individual words. Words used more often are larger and brighter (they grow logarithmically). There were a few points where the feed was lost, and it recounted the same status update over and over (you can tell where because the same words grow larger) but I decided to post this version anyway, because I still think it is interesting in this state. I have collected more data, such as word ordering, and will work on another version. done in Processing – source code is here (you need to add your twitter username and password)
The video above is a bit fuzzy – here’s a better image:
No CommentsI’m working on a music video for a song by PJE called The Employee and doing some tests. The idea is to create the surrealistic daydream of a 1950′s woman on her first day on the assembly line of a dreary, machine-like typist job. I’m doing all the visuals rendered in fluxus, cut with some excellent archival footage of office films from archive.org. This one, a 1950′s film called “Office Etiquette” is singular for having some really nice, sweeping, tracking chots mixed with good close-ups, which work well in a music video. The original has such a cheery attitude about mind-numbing, repetitive busywork that is practically crawling on its knees and begging to be subverted.
I will first cut the video as a straight music video, with close/wide/tracking shots and clean cuts to the beat, then add in the surrealistic, colorful 3D animations done using fluxus and bit by bit break down its sanity. Look here for more…
No Comments