[ Launch: FSS canvas + LEAP ] 5279204 by enjalot
[ Launch: FSS canvas example ] 5250737 by enjalot
[ Launch: basic FSS canvas ] 5250708 by enjalot
-
-
Save enjalot/5279204 to your computer and use it in GitHub Desktop.
FSS canvas + LEAP
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{"description":"FSS canvas + LEAP","endpoint":"","display":"div","public":true,"require":[{"name":"fss","url":"https://raw.github.com/wagerfield/flat-surface-shader/master/deploy/fss.min.js"}],"fileconfigs":{"inlet.js":{"default":true,"vim":false,"emacs":false,"fontSize":12},"_.md":{"default":true,"vim":false,"emacs":false,"fontSize":12},"config.json":{"default":true,"vim":false,"emacs":false,"fontSize":12},"index.html":{"default":true,"vim":false,"emacs":false,"fontSize":12},"leap.js":{"default":true,"vim":false,"emacs":false,"fontSize":12}},"fullscreen":false,"play":true,"loop":false,"restart":false,"autoinit":true,"pause":true,"loop_type":"period","bv":false,"nclones":15,"clone_opacity":0.4,"duration":3000,"ease":"linear","dt":0.01,"thumbnail":"http://i.imgur.com/ZWMMd4k.png"} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div id="output" class="container"> | |
</div> | |
<div id="vignette" class="overlay vignette"> | |
</div> | |
<div id="noise" class="overlay noise"> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//http://wagerfield.github.com/flat-surface-shader/ | |
//https://github.com/wagerfield/flat-surface-shader | |
//------------------------------ | |
// Mesh Properties | |
//------------------------------ | |
var MESH = { | |
width: 1.2, | |
height: 1.2, | |
depth: 10, | |
segments: 16, | |
slices: 8, | |
xRange: 0.8, | |
yRange: 0.1, | |
zRange: 1.0, | |
ambient: '#555555', | |
diffuse: '#FFFFFF', | |
speed: 0.002 | |
}; | |
//------------------------------ | |
// Light Properties | |
//------------------------------ | |
var LIGHT = { | |
count: 2, | |
xyScalar: 1, | |
zOffset: 100, | |
ambient: '#880066', | |
diffuse: '#FF8800', | |
speed: 0.001, | |
gravity: 1200, | |
dampening: 0.95, | |
minLimit: 10, | |
maxLimit: null, | |
minDistance: 20, | |
maxDistance: 400, | |
autopilot: false, | |
draw: true, | |
bounds: FSS.Vector3.create(), | |
step: FSS.Vector3.create( | |
Math.randomInRange(0.2, 1.0), | |
Math.randomInRange(0.2, 1.0), | |
Math.randomInRange(0.2, 1.0) | |
) | |
}; | |
//------------------------------ | |
// Render Properties | |
//------------------------------ | |
var SVG = 'svg'; | |
var CANVAS = 'canvas'; | |
var RENDER = { | |
renderer: CANVAS | |
}; | |
//------------------------------ | |
// Export Properties | |
//------------------------------ | |
var EXPORT = { | |
width: 2000, | |
height: 1000, | |
drawLights: false, | |
minLightX: 0.4, | |
maxLightX: 0.6, | |
minLightY: 0.2, | |
maxLightY: 0.4, | |
"export": function() { | |
var l, x, y, light, | |
depth = MESH.depth, | |
zOffset = LIGHT.zOffset, | |
autopilot = LIGHT.autopilot, | |
scalar = this.width / renderer.width; | |
LIGHT.autopilot = true; | |
LIGHT.draw = this.drawLights; | |
LIGHT.zOffset *= scalar; | |
MESH.depth *= scalar; | |
resize(this.width, this.height); | |
for (l = scene.lights.length - 1; l >= 0; l--) { | |
light = scene.lights[l]; | |
x = Math.randomInRange(this.width*this.minLightX, this.width*this.maxLightX); | |
y = Math.randomInRange(this.height*this.minLightY, this.height*this.maxLightY); | |
FSS.Vector3.set(light.position, x, this.height-y, this.lightZ); | |
FSS.Vector3.subtract(light.position, center); | |
} | |
update(); | |
render(); | |
switch(RENDER.renderer) { | |
case CANVAS: | |
window.open(canvasRenderer.element.toDataURL(), '_blank'); | |
break; | |
case SVG: | |
var data = encodeURIComponent(output.innerHTML); | |
var url = "data:image/svg+xml," + data; | |
window.open(url, '_blank'); | |
break; | |
} | |
LIGHT.draw = true; | |
LIGHT.autopilot = autopilot; | |
LIGHT.zOffset = zOffset; | |
MESH.depth = depth; | |
resize(container.offsetWidth, container.offsetHeight); | |
} | |
}; | |
//------------------------------ | |
// UI Properties | |
//------------------------------ | |
var UI = { | |
show: true | |
}; | |
//------------------------------ | |
// Global Properties | |
//------------------------------ | |
var now, start = Date.now(); | |
var center = FSS.Vector3.create(); | |
var attractor = FSS.Vector3.create(); | |
var renderer, scene, mesh, geometry, material; | |
var canvasRenderer, svgRenderer; | |
var gui, autopilotController; | |
var container = d3.select("#display").node(); | |
var output = d3.select("#output").node(); | |
var noise = d3.select("#noise").node(); | |
//------------------------------ | |
// Methods | |
//------------------------------ | |
tributary.run = function(g,t) { | |
now = Date.now() - start; | |
update(); | |
render(); | |
} | |
function initialise() { | |
createRenderer(); | |
createScene(); | |
createMesh(); | |
createLights(); | |
//addEventListeners(); | |
//addControls(); | |
resize(container.offsetWidth, container.offsetHeight); | |
//animate(); | |
} | |
function createRenderer() { | |
svgRenderer = new FSS.SVGRenderer(); | |
canvasRenderer = new FSS.CanvasRenderer(); | |
setRenderer(RENDER.renderer); | |
} | |
function setRenderer(index) { | |
if (renderer) { | |
output.removeChild(renderer.element); | |
} | |
switch(index) { | |
case CANVAS: | |
renderer = canvasRenderer; | |
break; | |
case SVG: | |
renderer = svgRenderer; | |
break; | |
} | |
renderer.setSize(container.offsetWidth, container.offsetHeight); | |
output.appendChild(renderer.element); | |
} | |
function createScene() { | |
scene = new FSS.Scene(); | |
} | |
function createMesh() { | |
scene.remove(mesh); | |
renderer.clear(); | |
geometry = new FSS.Plane(MESH.width * renderer.width, MESH.height * renderer.height, MESH.segments, MESH.slices); | |
material = new FSS.Material(MESH.ambient, MESH.diffuse); | |
mesh = new FSS.Mesh(geometry, material); | |
scene.add(mesh); | |
// Augment vertices for animation | |
var v, vertex; | |
for (v = geometry.vertices.length - 1; v >= 0; v--) { | |
vertex = geometry.vertices[v]; | |
vertex.anchor = FSS.Vector3.clone(vertex.position); | |
vertex.step = FSS.Vector3.create( | |
Math.randomInRange(0.2, 1.0), | |
Math.randomInRange(0.2, 1.0), | |
Math.randomInRange(0.2, 1.0) | |
); | |
vertex.time = Math.randomInRange(0, Math.PIM2); | |
} | |
} | |
function createLights() { | |
var l, light; | |
for (l = scene.lights.length - 1; l >= 0; l--) { | |
light = scene.lights[l]; | |
scene.remove(light); | |
} | |
renderer.clear(); | |
for (l = 0; l < LIGHT.count; l++) { | |
light = new FSS.Light(LIGHT.ambient, LIGHT.diffuse); | |
light.ambientHex = light.ambient.format(); | |
light.diffuseHex = light.diffuse.format(); | |
scene.add(light); | |
// Augment light for animation | |
light.mass = Math.randomInRange(0.5, 1); | |
light.velocity = FSS.Vector3.create(); | |
light.acceleration = FSS.Vector3.create(); | |
light.force = FSS.Vector3.create(); | |
// Ring SVG Circle | |
light.ring = document.createElementNS(FSS.SVGNS, 'circle'); | |
light.ring.setAttributeNS(null, 'stroke', light.ambientHex); | |
light.ring.setAttributeNS(null, 'stroke-width', '0.5'); | |
light.ring.setAttributeNS(null, 'fill', 'none'); | |
light.ring.setAttributeNS(null, 'r', '10'); | |
// Core SVG Circle | |
light.core = document.createElementNS(FSS.SVGNS, 'circle'); | |
light.core.setAttributeNS(null, 'fill', light.diffuseHex); | |
light.core.setAttributeNS(null, 'r', '4'); | |
} | |
} | |
function resize(width, height) { | |
renderer.setSize(width, height); | |
FSS.Vector3.set(center, renderer.halfWidth, renderer.halfHeight); | |
createMesh(); | |
} | |
function update() { | |
var ox, oy, oz, l, light, v, vertex, offset = MESH.depth/2; | |
// Update Bounds | |
FSS.Vector3.copy(LIGHT.bounds, center); | |
FSS.Vector3.multiplyScalar(LIGHT.bounds, LIGHT.xyScalar); | |
// Update Attractor | |
FSS.Vector3.setZ(attractor, LIGHT.zOffset); | |
// Overwrite the Attractor position | |
if (LIGHT.autopilot) { | |
ox = Math.sin(LIGHT.step[0] * now * LIGHT.speed); | |
oy = Math.cos(LIGHT.step[1] * now * LIGHT.speed); | |
FSS.Vector3.set(attractor, | |
LIGHT.bounds[0]*ox, | |
LIGHT.bounds[1]*oy, | |
LIGHT.zOffset); | |
} | |
// Animate Lights | |
for (l = scene.lights.length - 1; l >= 0; l--) { | |
light = scene.lights[l]; | |
// Reset the z position of the light | |
FSS.Vector3.setZ(light.position, LIGHT.zOffset); | |
// Calculate the force Luke! | |
var D = Math.clamp(FSS.Vector3.distanceSquared(light.position, attractor), LIGHT.minDistance, LIGHT.maxDistance); | |
var F = LIGHT.gravity * light.mass / D; | |
FSS.Vector3.subtractVectors(light.force, attractor, light.position); | |
FSS.Vector3.normalise(light.force); | |
FSS.Vector3.multiplyScalar(light.force, F); | |
// Update the light position | |
FSS.Vector3.set(light.acceleration); | |
FSS.Vector3.add(light.acceleration, light.force); | |
FSS.Vector3.add(light.velocity, light.acceleration); | |
FSS.Vector3.multiplyScalar(light.velocity, LIGHT.dampening); | |
FSS.Vector3.limit(light.velocity, LIGHT.minLimit, LIGHT.maxLimit); | |
FSS.Vector3.add(light.position, light.velocity); | |
} | |
// Animate Vertices | |
for (v = geometry.vertices.length - 1; v >= 0; v--) { | |
vertex = geometry.vertices[v]; | |
ox = Math.sin(vertex.time + vertex.step[0] * now * MESH.speed); | |
oy = Math.cos(vertex.time + vertex.step[1] * now * MESH.speed); | |
oz = Math.sin(vertex.time + vertex.step[2] * now * MESH.speed); | |
FSS.Vector3.set(vertex.position, | |
MESH.xRange*geometry.segmentWidth*ox, | |
MESH.yRange*geometry.sliceHeight*oy, | |
MESH.zRange*offset*oz - offset); | |
FSS.Vector3.add(vertex.position, vertex.anchor); | |
} | |
// Set the Geometry to dirty | |
geometry.dirty = true; | |
} | |
function render() { | |
renderer.render(scene); | |
// Draw Lights | |
if (LIGHT.draw) { | |
var l, lx, ly, light; | |
for (l = scene.lights.length - 1; l >= 0; l--) { | |
light = scene.lights[l]; | |
lx = light.position[0]; | |
ly = light.position[1]; | |
switch(RENDER.renderer) { | |
case CANVAS: | |
renderer.context.lineWidth = 0.5; | |
renderer.context.beginPath(); | |
renderer.context.arc(lx, ly, 10, 0, Math.PIM2); | |
renderer.context.strokeStyle = light.ambientHex; | |
renderer.context.stroke(); | |
renderer.context.beginPath(); | |
renderer.context.arc(lx, ly, 4, 0, Math.PIM2); | |
renderer.context.fillStyle = light.diffuseHex; | |
renderer.context.fill(); | |
break; | |
case SVG: | |
lx += renderer.halfWidth; | |
ly = renderer.halfHeight - ly; | |
light.core.setAttributeNS(null, 'cx', lx); | |
light.core.setAttributeNS(null, 'cy', ly); | |
renderer.element.appendChild(light.core); | |
light.ring.setAttributeNS(null, 'cx', lx); | |
light.ring.setAttributeNS(null, 'cy', ly); | |
renderer.element.appendChild(light.ring); | |
break; | |
} | |
} | |
} | |
} | |
//------------------------------ | |
// Callbacks | |
//------------------------------ | |
d3.select("#display").on("click", onMouseClick); | |
function onMouseClick() { | |
FSS.Vector3.set(attractor, d3.event.x, renderer.height - d3.event.y); | |
FSS.Vector3.subtract(attractor, center); | |
LIGHT.autopilot = !LIGHT.autopilot; | |
autopilotController.updateDisplay(); | |
} | |
/*d3.select("#display").on("mousemove", onMouseMove); | |
function onMouseMove() { | |
FSS.Vector3.set(attractor, d3.event.x, renderer.height - d3.event.y); | |
FSS.Vector3.subtract(attractor, center); | |
}*/ | |
var xscale = d3.scale.linear() | |
.domain([-200, 200]) | |
.range([0, tributary.sw]) | |
var yscale = d3.scale.linear() | |
.domain([-100, 150]) | |
.range([tributary.sh, 0]); | |
var zscale = d3.scale.linear() | |
.domain([100, 400]) | |
.range([20, 400]); | |
function onLeap(d) { | |
if(d.hands && d.hands[0]) { | |
var x = d.hands[0].palmPosition[0]; | |
var y = d.hands[0].palmPosition[2]; | |
var z = d.hands[0].palmPosition[1]; | |
LIGHT.zOffset = zscale(z); | |
FSS.Vector3.set(attractor, xscale(x), yscale(y)); | |
FSS.Vector3.subtract(attractor, center); | |
} | |
} | |
// Let there be light! | |
initialise(); | |
tributary.leap.events.off("frame"); | |
tributary.leap.events.on("frame", function(d) { | |
//console.log(d); | |
onLeap(d); | |
}) | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
tributary.leap = { | |
events: _.clone(Backbone.Events) | |
}; | |
// Support both the WebSocket and MozWebSocket objects | |
if ((typeof(WebSocket) == 'undefined') && | |
(typeof(MozWebSocket) != 'undefined')) { | |
WebSocket = MozWebSocket; | |
} | |
// Create the socket with event handlers | |
tributary.leap.init = function() { | |
if(tributary.ws) { | |
tributary.ws.close(); | |
} | |
console.log("Starting"); | |
//Create and open the socket | |
tributary.ws = new WebSocket("ws://localhost:6437/"); | |
var ws = tributary.ws; | |
// On successful connection | |
ws.onopen = function(event) { | |
console.log("Open"); | |
tributary.leap.connected = true; | |
tributary.leap.events.trigger("open"); | |
}; | |
// On message received | |
ws.onmessage = function(event) { | |
tributary.leap.events.trigger("frame", JSON.parse(event.data)); | |
}; | |
// On socket close | |
ws.onclose = function(event) { | |
ws = null; | |
tributary.leap.connected = false; | |
tributary.leap.events.trigger("close"); | |
} | |
//On socket error | |
ws.onerror = function(event) { | |
console.error("Received error"); | |
}; | |
} | |
var socketState; | |
if(!tributary.ws || tributary.ws.readyState != 1) { | |
tributary.leap.connected = false; | |
} else { | |
tributary.leap.connected = true; | |
} | |
tributary.leap.toggle = function() { | |
if(tributary.ws.readyState === 1) { | |
tributary.ws.close(); | |
} else { | |
tributary.leap.init(); | |
} | |
} | |
tributary.leap.init(); | |
tributary.events.on("restart", function() { | |
tributary.leap.init(); | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment