On Github maniart / brooklyn.js-slides
...and to many many others.
Being web based should not dictate the mode of interaction: Making it site-specific.
// Particle constructor
var Particle = function(args) {
this.x = Math.random() * W;
this.y = Math.random() * H;
this.vx = -1 + Math.random() * 2;
this.vy = -1 + Math.random() * 2;
this.radius = args.radius;
};
function distance(p1, p2) {
var dx = p1.x - p2.x,
dy = p1.y - p2.y;
dist = Math.sqrt(dx * dx + dy * dy);
if (dist <= args.minDist) {
canvasCtx.beginPath();
canvasCtx.strokeStyle = args.setColor();
canvasCtx.lineWidth = args.lineWidth;
canvasCtx.moveTo(p1.x, p1.y);
canvasCtx.lineTo(p2.x, p2.y);
canvasCtx.stroke();
canvasCtx.closePath();
var ax = dx / (args.minDist * 1000),
ay = dy / (args.minDist * 1000);
p1.vx -= (args.minDist / Math.pow(100,.5)) * ax;
p1.vy -= (args.minDist / Math.pow(100,.5)) * ay;
p2.vx += (args.minDist / Math.pow(100,.5)) * ax;
p2.vy += (args.minDist / Math.pow(100,.5)) * ay;
}
};
function fastAbs(value) {
return (value ^ (value >> 31)) - (value >> 31);
};
function threshold(value) {
return (value > 0x15) ? 0xFF : 0;
};
function differenceAccuracy(target, data1, data2) {
if (data1.length != data2.length) return null;
var i = 0;
while (i < (data1.length * 0.25)) {
var average1 = (data1[4*i] + data1[4*i+1] + data1[4*i+2]) / 2.5;
var average2 = (data2[4*i] + data2[4*i+1] + data2[4*i+2]) / 2.5;
var diff = threshold(fastAbs(average1 - average2));
target[4*i] = diff;
target[4*i+1] = diff;
target[4*i+2] = diff;
target[4*i+3] = 0xFF;
++i;
}
};
function blend() {
var width = DOM.normalImage.width,
height = DOM.normalImage.height,
sourceData = normalImageCtx.getImageData(0, 0, width, height);
if (!lastImageData) lastImageData = normalImageCtx.getImageData(0, 0, width, height);
var blendedData = normalImageCtx.createImageData(width, height);
differenceAccuracy(blendedData.data, sourceData.data, lastImageData.data);
diffImageCtx.putImageData(blendedData, 0, 0);
lastImageData = sourceData;
};
function checkAreas() {
for (var r=1; r<6; ++r) {
var blendedData = diffImageCtx.getImageData(1/7*r*webcam.width, 1/8*3*webcam.height, webcam.width/8, 1/7*webcam.height);
var i = 0;
var average = 0;
while (i < (blendedData.data.length * 0.25)) {
average += (blendedData.data[i*4] + blendedData.data[i*4+1] + blendedData.data[i*4+2]) / 3;
++i;
}
average = Math.round(average / (blendedData.data.length * 0.25));
if (average > 10) {
switch(r) {
case 1:
shab.isHit = true;
break;
case 2:
zibast.isHit = true;
break;
case 3:
bihodeh.isHit = true;
break;
case 4:
ke.isHit = true;
break;
case 5:
agar.isHit = true;
break;
}
} else {
switch(r) {
case 1:
shab.isHit = false;
break;
case 2:
zibast.isHit = false;
break;
case 3:
bihodeh.isHit = false;
break;
case 4:
ke.isHit = false;
break;
case 5:
agar.isHit = false;
break;
}
}
}
function draw() {
clear();
for (var i = particles.length - 1; i >= 0; i --) {
particles[i].draw();
//canvasCtx.drawImage(images.agar, particles[0].x, particles[0].y, 25, 21);
//canvasCtx.drawImage(images.ke, particles[1].x, particles[1].y, 39, 29);
//canvasCtx.drawImage(images.bihodeh, particles[2].x, particles[2].y, 64, 41);
//canvasCtx.drawImage(images.shab, particles[4].x, particles[4].y, 61, 35);
};
update();
/* hack: drawing words in html for exhibition shhhhhhh! */
//canvasCtx.drawImage(images.agar, 1/7*5*DOM.canvas.width, 1/8*3*DOM.canvas.height, 51, 43);
//canvasCtx.drawImage(images.ke, 1/7*4*DOM.canvas.width, 1/8*3*DOM.canvas.height, 40, 29);
//canvasCtx.drawImage(images.bihodeh, 1/7*3*DOM.canvas.width, 1/8*3*DOM.canvas.height, 97, 38);
//canvasCtx.drawImage(images.zibast, 1/7*2*DOM.canvas.width, 1/8*3*DOM.canvas.height, 103, 41);
//canvasCtx.drawImage(images.shab, 1/7*1*DOM.canvas.width, 1/8*3*DOM.canvas.height, 64, 41);
}
Are works of art lifeless objects?
... Or do they gaze back at us?
Lesson learned: Framing an LCD is mad fun.
Lesson learned: Framing an LCD is mad fun.
decodeBase64Image = function(dataString) {
var matches = dataString.match(/^data:([A-Za-z-+\/]+);base64,(.+)$/),
response = {};
if (matches.length !== 3) {
throw new Error('Invalid input string');
}
response.type = matches[1];
response.data = new Buffer(matches[2], 'base64');
return response;
};
var cv = require('opencv');
cv.readImage(imageBuffer.data, function(err, im){
if(err) throw err;
im.detectObject(cv.FACE_CASCADE, {}, function(err, faces){
/* OMG! Faces! */
});
});
io.on('connection', function(socket) {
socket.on('image', function(data){
imageBuffer = decodeBase64Image(data);
});
socket.volatile.emit('faceDetected', faces);
socket.broadcast.volatile.emit('faceDetected', faces);
socket.volatile.emit('faceAdded', [faceCount, totalFaceCount]);
socket.broadcast.volatile.emit('faceAdded', faceCount);
socket.volatile.emit('faceRemoved', [faceCount, totalFaceCount]);
socket.broadcast.volatile.emit('faceRemoved', [faceCount, totalFaceCount]);
});
socket.on('faceDetected', function(imageBuffer){
draw(imageBuffer);
});
socket.on('closer', function() {
updateText(function() {
var index = Math.ceil(Math.random() * sentences.interactive.closer.length-1);
return sentences.interactive.closer[index];
});
});
socket.on('farther', function() {
updateText(function() {
var index = Math.ceil(Math.random() * sentences.interactive.farther.length-1);
return sentences.interactive.farther[index];
});
});
socket.on('faceAdded', function(args) {
updateText(function() {
var index = Math.ceil(Math.random() * sentences.predefined.length-1);
return typeof sentences.predefined[index] === 'function' ? sentences.predefined[index](args) : sentences.predefined[index];
});
});
socket.on('faceRemoved', function(args) {
updateText(function() {
var index = Math.ceil(Math.random() * sentences.predefined.length-1);
return typeof sentences.predefined[index] === 'function' ? sentences.predefined[index](args) : sentences.predefined[index];
});
});
Shout out to this rad fellow.